// 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::buffer::BufferAccess;
use crate::buffer::TypedBufferAccess;
use crate::command_buffer::pool::standard::StandardCommandPoolAlloc;
use crate::command_buffer::pool::standard::StandardCommandPoolBuilder;
use crate::command_buffer::pool::CommandPool;
use crate::command_buffer::pool::CommandPoolBuilderAlloc;
use crate::command_buffer::synced::SyncCommandBuffer;
use crate::command_buffer::synced::SyncCommandBufferBuilder;
use crate::command_buffer::synced::SyncCommandBufferBuilderError;
use crate::command_buffer::sys::UnsafeCommandBuffer;
use crate::command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
use crate::command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
use crate::command_buffer::sys::UnsafeCommandBufferBuilderImageBlit;
use crate::command_buffer::sys::UnsafeCommandBufferBuilderImageCopy;
use crate::command_buffer::validity::*;
use crate::command_buffer::CommandBufferExecError;
use crate::command_buffer::CommandBufferInheritance;
use crate::command_buffer::CommandBufferInheritanceRenderPass;
use crate::command_buffer::CommandBufferLevel;
use crate::command_buffer::CommandBufferUsage;
use crate::command_buffer::DispatchIndirectCommand;
use crate::command_buffer::DrawIndexedIndirectCommand;
use crate::command_buffer::DrawIndirectCommand;
use crate::command_buffer::DynamicState;
use crate::command_buffer::ImageUninitializedSafe;
use crate::command_buffer::PrimaryCommandBuffer;
use crate::command_buffer::SecondaryCommandBuffer;
use crate::command_buffer::StateCacher;
use crate::command_buffer::StateCacherOutcome;
use crate::command_buffer::SubpassContents;
use crate::descriptor_set::DescriptorSetWithOffsets;
use crate::descriptor_set::DescriptorSetsCollection;
use crate::device::physical::QueueFamily;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::device::Queue;
use crate::format::ClearValue;
use crate::format::FormatTy;
use crate::format::Pixel;
use crate::image::ImageAccess;
use crate::image::ImageAspect;
use crate::image::ImageAspects;
use crate::image::ImageLayout;
use crate::pipeline::depth_stencil::StencilFaces;
use crate::pipeline::input_assembly::Index;
use crate::pipeline::layout::PipelineLayout;
use crate::pipeline::vertex::VertexSource;
use crate::pipeline::ComputePipelineAbstract;
use crate::pipeline::GraphicsPipelineAbstract;
use crate::pipeline::PipelineBindPoint;
use crate::query::QueryControlFlags;
use crate::query::QueryPipelineStatisticFlags;
use crate::query::QueryPool;
use crate::query::QueryResultElement;
use crate::query::QueryResultFlags;
use crate::query::QueryType;
use crate::render_pass::Framebuffer;
use crate::render_pass::FramebufferAbstract;
use crate::render_pass::LoadOp;
use crate::render_pass::RenderPass;
use crate::render_pass::Subpass;
use crate::sampler::Filter;
use crate::sync::AccessCheckError;
use crate::sync::AccessFlags;
use crate::sync::GpuFuture;
use crate::sync::PipelineMemoryAccess;
use crate::sync::PipelineStage;
use crate::sync::PipelineStages;
use crate::DeviceSize;
use crate::VulkanObject;
use crate::{OomError, SafeDeref};
use fnv::FnvHashMap;
use std::error;
use std::ffi::CStr;
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops::Range;
use std::slice;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::sync::Arc;

/// Note that command buffers allocated from the default command pool (`Arc<StandardCommandPool>`)
/// don't implement the `Send` and `Sync` traits. If you use this pool, then the
/// `AutoCommandBufferBuilder` will not implement `Send` and `Sync` either. Once a command buffer
/// is built, however, it *does* implement `Send` and `Sync`.
pub struct AutoCommandBufferBuilder<L, P = StandardCommandPoolBuilder> {
    inner: SyncCommandBufferBuilder,
    pool_builder_alloc: P, // Safety: must be dropped after `inner`
    state_cacher: StateCacher,

    // The queue family that this command buffer is being created for.
    queue_family_id: u32,

    // The inheritance for secondary command buffers.
    inheritance: Option<CommandBufferInheritance<Box<dyn FramebufferAbstract + Send + Sync>>>,

    // Usage flags passed when creating the command buffer.
    usage: CommandBufferUsage,

    // If we're inside a render pass, contains the render pass state.
    render_pass_state: Option<RenderPassState>,

    // If any queries are active, this hashmap contains their state.
    query_state: FnvHashMap<ash::vk::QueryType, QueryState>,

    _data: PhantomData<L>,
}

// The state of the current render pass, specifying the pass, subpass index and its intended contents.
struct RenderPassState {
    subpass: (Arc<RenderPass>, u32),
    contents: SubpassContents,
    framebuffer: ash::vk::Framebuffer, // Always null for secondary command buffers
}

// The state of an active query.
struct QueryState {
    query_pool: ash::vk::QueryPool,
    query: u32,
    ty: QueryType,
    flags: QueryControlFlags,
    in_subpass: bool,
}

impl AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder> {
    /// Starts building a primary command buffer.
    #[inline]
    pub fn primary(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
    ) -> Result<
        AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
        OomError,
    > {
        AutoCommandBufferBuilder::with_level(
            device,
            queue_family,
            usage,
            CommandBufferLevel::primary(),
        )
    }
}

impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder> {
    /// Starts building a secondary compute command buffer.
    #[inline]
    pub fn secondary_compute(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
    ) -> Result<
        AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
        OomError,
    > {
        let level = CommandBufferLevel::secondary(None, QueryPipelineStatisticFlags::none());
        AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
    }

    /// Same as `secondary_compute`, but allows specifying how queries are being inherited.
    #[inline]
    pub fn secondary_compute_inherit_queries(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
        occlusion_query: Option<QueryControlFlags>,
        query_statistics_flags: QueryPipelineStatisticFlags,
    ) -> Result<
        AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
        BeginError,
    > {
        if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
            return Err(BeginError::InheritedQueriesFeatureNotEnabled);
        }

        if query_statistics_flags.count() > 0
            && !device.enabled_features().pipeline_statistics_query
        {
            return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
        }

        let level = CommandBufferLevel::secondary(occlusion_query, query_statistics_flags);
        Ok(AutoCommandBufferBuilder::with_level(
            device,
            queue_family,
            usage,
            level,
        )?)
    }

    /// Starts building a secondary graphics command buffer.
    #[inline]
    pub fn secondary_graphics(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
        subpass: Subpass,
    ) -> Result<
        AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
        OomError,
    > {
        let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
            render_pass: Some(CommandBufferInheritanceRenderPass {
                subpass,
                framebuffer: None::<Arc<Framebuffer<()>>>,
            }),
            occlusion_query: None,
            query_statistics_flags: QueryPipelineStatisticFlags::none(),
        });

        AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
    }

    /// Same as `secondary_graphics`, but allows specifying how queries are being inherited.
    #[inline]
    pub fn secondary_graphics_inherit_queries(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
        subpass: Subpass,
        occlusion_query: Option<QueryControlFlags>,
        query_statistics_flags: QueryPipelineStatisticFlags,
    ) -> Result<
        AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
        BeginError,
    > {
        if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
            return Err(BeginError::InheritedQueriesFeatureNotEnabled);
        }

        if query_statistics_flags.count() > 0
            && !device.enabled_features().pipeline_statistics_query
        {
            return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
        }

        let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
            render_pass: Some(CommandBufferInheritanceRenderPass {
                subpass,
                framebuffer: None::<Arc<Framebuffer<()>>>,
            }),
            occlusion_query,
            query_statistics_flags,
        });

        Ok(AutoCommandBufferBuilder::with_level(
            device,
            queue_family,
            usage,
            level,
        )?)
    }
}

impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
    // Actual constructor. Private.
    fn with_level<F>(
        device: Arc<Device>,
        queue_family: QueueFamily,
        usage: CommandBufferUsage,
        level: CommandBufferLevel<F>,
    ) -> Result<AutoCommandBufferBuilder<L, StandardCommandPoolBuilder>, OomError>
    where
        F: FramebufferAbstract + Clone + Send + Sync + 'static,
    {
        let (inheritance, render_pass_state) = match &level {
            CommandBufferLevel::Primary => (None, None),
            CommandBufferLevel::Secondary(inheritance) => {
                let (render_pass, render_pass_state) = match inheritance.render_pass.as_ref() {
                    Some(CommandBufferInheritanceRenderPass {
                        subpass,
                        framebuffer,
                    }) => {
                        let render_pass = CommandBufferInheritanceRenderPass {
                            subpass: Subpass::from(subpass.render_pass().clone(), subpass.index())
                                .unwrap(),
                            framebuffer: framebuffer
                                .as_ref()
                                .map(|f| Box::new(f.clone()) as Box<_>),
                        };
                        let render_pass_state = RenderPassState {
                            subpass: (subpass.render_pass().clone(), subpass.index()),
                            contents: SubpassContents::Inline,
                            framebuffer: ash::vk::Framebuffer::null(), // Only needed for primary command buffers
                        };
                        (Some(render_pass), Some(render_pass_state))
                    }
                    None => (None, None),
                };

                (
                    Some(CommandBufferInheritance {
                        render_pass,
                        occlusion_query: inheritance.occlusion_query,
                        query_statistics_flags: inheritance.query_statistics_flags,
                    }),
                    render_pass_state,
                )
            }
        };

        unsafe {
            let pool = Device::standard_command_pool(&device, queue_family);
            let pool_builder_alloc = pool
                .alloc(!matches!(level, CommandBufferLevel::Primary), 1)?
                .next()
                .expect("Requested one command buffer from the command pool, but got zero.");
            let inner = SyncCommandBufferBuilder::new(pool_builder_alloc.inner(), level, usage)?;

            Ok(AutoCommandBufferBuilder {
                inner,
                pool_builder_alloc,
                state_cacher: StateCacher::new(),
                queue_family_id: queue_family.id(),
                render_pass_state,
                query_state: FnvHashMap::default(),
                inheritance,
                usage,
                _data: PhantomData,
            })
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub enum BeginError {
    /// Occlusion query inheritance was requested, but the `inherited_queries` feature was not enabled.
    InheritedQueriesFeatureNotEnabled,
    /// Not enough memory.
    OomError(OomError),
    /// Pipeline statistics query inheritance was requested, but the `pipeline_statistics_query` feature was not enabled.
    PipelineStatisticsQueryFeatureNotEnabled,
}

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

impl fmt::Display for BeginError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            fmt,
            "{}",
            match *self {
                Self::InheritedQueriesFeatureNotEnabled => {
                    "occlusion query inheritance was requested but the corresponding feature \
                 wasn't enabled"
                }
                Self::OomError(_) => "not enough memory available",
                Self::PipelineStatisticsQueryFeatureNotEnabled => {
                    "pipeline statistics query inheritance was requested but the corresponding \
                 feature wasn't enabled"
                }
            }
        )
    }
}

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

impl<P> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<P::Alloc>, P>
where
    P: CommandPoolBuilderAlloc,
{
    /// Builds the command buffer.
    #[inline]
    pub fn build(self) -> Result<PrimaryAutoCommandBuffer<P::Alloc>, BuildError> {
        if self.render_pass_state.is_some() {
            return Err(AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass.into());
        }

        if !self.query_state.is_empty() {
            return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
        }

        let submit_state = match self.usage {
            CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
                in_use: AtomicBool::new(false),
            },
            CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
            CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
                already_submitted: AtomicBool::new(false),
            },
        };

        Ok(PrimaryAutoCommandBuffer {
            inner: self.inner.build()?,
            pool_alloc: self.pool_builder_alloc.into_alloc(),
            submit_state,
        })
    }
}

impl<P> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<P::Alloc>, P>
where
    P: CommandPoolBuilderAlloc,
{
    /// Builds the command buffer.
    #[inline]
    pub fn build(self) -> Result<SecondaryAutoCommandBuffer<P::Alloc>, BuildError> {
        if !self.query_state.is_empty() {
            return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
        }

        let submit_state = match self.usage {
            CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
                in_use: AtomicBool::new(false),
            },
            CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
            CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
                already_submitted: AtomicBool::new(false),
            },
        };

        Ok(SecondaryAutoCommandBuffer {
            inner: self.inner.build()?,
            pool_alloc: self.pool_builder_alloc.into_alloc(),
            inheritance: self.inheritance.unwrap(),
            submit_state,
        })
    }
}

impl<L, P> AutoCommandBufferBuilder<L, P> {
    #[inline]
    fn ensure_outside_render_pass(&self) -> Result<(), AutoCommandBufferBuilderContextError> {
        if self.render_pass_state.is_some() {
            return Err(AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass);
        }

        Ok(())
    }

    #[inline]
    fn ensure_inside_render_pass_inline<Gp>(
        &self,
        pipeline: &Gp,
    ) -> Result<(), AutoCommandBufferBuilderContextError>
    where
        Gp: ?Sized + GraphicsPipelineAbstract,
    {
        let render_pass_state = self
            .render_pass_state
            .as_ref()
            .ok_or(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass)?;

        // Subpass must be for inline commands
        if render_pass_state.contents != SubpassContents::Inline {
            return Err(AutoCommandBufferBuilderContextError::WrongSubpassType);
        }

        // Subpasses must be the same.
        if pipeline.subpass().index() != render_pass_state.subpass.1 {
            return Err(AutoCommandBufferBuilderContextError::WrongSubpassIndex);
        }

        // Render passes must be compatible.
        if !pipeline
            .subpass()
            .render_pass()
            .desc()
            .is_compatible_with_desc(&render_pass_state.subpass.0.desc())
        {
            return Err(AutoCommandBufferBuilderContextError::IncompatibleRenderPass);
        }

        Ok(())
    }

    #[inline]
    fn queue_family(&self) -> QueueFamily {
        self.device()
            .physical_device()
            .queue_family_by_id(self.queue_family_id)
            .unwrap()
    }

    /// Adds a command that copies an image to another.
    ///
    /// Copy operations have several restrictions:
    ///
    /// - Copy operations are only allowed on queue families that support transfer, graphics, or
    ///   compute operations.
    /// - The number of samples in the source and destination images must be equal.
    /// - The size of the uncompressed element format of the source image must be equal to the
    ///   compressed element format of the destination.
    /// - If you copy between depth, stencil or depth-stencil images, the format of both images
    ///   must match exactly.
    /// - For two-dimensional images, the Z coordinate must be 0 for the image offsets and 1 for
    ///   the extent. Same for the Y coordinate for one-dimensional images.
    /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
    ///
    /// If `layer_count` is greater than 1, the copy will happen between each individual layer as
    /// if they were separate images.
    ///
    /// # Panic
    ///
    /// - Panics if the source or the destination was not created with `device`.
    ///
    pub fn copy_image<S, D>(
        &mut self,
        source: S,
        source_offset: [i32; 3],
        source_base_array_layer: u32,
        source_mip_level: u32,
        destination: D,
        destination_offset: [i32; 3],
        destination_base_array_layer: u32,
        destination_mip_level: u32,
        extent: [u32; 3],
        layer_count: u32,
    ) -> Result<&mut Self, CopyImageError>
    where
        S: ImageAccess + Send + Sync + 'static,
        D: ImageAccess + Send + Sync + 'static,
    {
        unsafe {
            self.ensure_outside_render_pass()?;

            check_copy_image(
                self.device(),
                &source,
                source_offset,
                source_base_array_layer,
                source_mip_level,
                &destination,
                destination_offset,
                destination_base_array_layer,
                destination_mip_level,
                extent,
                layer_count,
            )?;

            let copy = UnsafeCommandBufferBuilderImageCopy {
                // TODO: Allowing choosing a subset of the image aspects, but note that if color
                // is included, neither depth nor stencil may.
                aspects: ImageAspects {
                    color: source.has_color(),
                    depth: !source.has_color() && source.has_depth() && destination.has_depth(),
                    stencil: !source.has_color()
                        && source.has_stencil()
                        && destination.has_stencil(),
                    ..ImageAspects::none()
                },
                source_mip_level,
                destination_mip_level,
                source_base_array_layer,
                destination_base_array_layer,
                layer_count,
                source_offset,
                destination_offset,
                extent,
            };

            // TODO: Allow choosing layouts, but note that only Transfer*Optimal and General are
            // valid.
            self.inner.copy_image(
                source,
                ImageLayout::TransferSrcOptimal,
                destination,
                ImageLayout::TransferDstOptimal,
                iter::once(copy),
            )?;
            Ok(self)
        }
    }

    /// Adds a command that blits an image to another.
    ///
    /// A *blit* is similar to an image copy operation, except that the portion of the image that
    /// is transferred can be resized. You choose an area of the source and an area of the
    /// destination, and the implementation will resize the area of the source so that it matches
    /// the size of the area of the destination before writing it.
    ///
    /// Blit operations have several restrictions:
    ///
    /// - Blit operations are only allowed on queue families that support graphics operations.
    /// - The format of the source and destination images must support blit operations, which
    ///   depends on the Vulkan implementation. Vulkan guarantees that some specific formats must
    ///   always be supported. See tables 52 to 61 of the specifications.
    /// - Only single-sampled images are allowed.
    /// - You can only blit between two images whose formats belong to the same type. The types
    ///   are: floating-point, signed integers, unsigned integers, depth-stencil.
    /// - If you blit between depth, stencil or depth-stencil images, the format of both images
    ///   must match exactly.
    /// - If you blit between depth, stencil or depth-stencil images, only the `Nearest` filter is
    ///   allowed.
    /// - For two-dimensional images, the Z coordinate must be 0 for the top-left offset and 1 for
    ///   the bottom-right offset. Same for the Y coordinate for one-dimensional images.
    /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
    ///
    /// If `layer_count` is greater than 1, the blit will happen between each individual layer as
    /// if they were separate images.
    ///
    /// # Panic
    ///
    /// - Panics if the source or the destination was not created with `device`.
    ///
    pub fn blit_image<S, D>(
        &mut self,
        source: S,
        source_top_left: [i32; 3],
        source_bottom_right: [i32; 3],
        source_base_array_layer: u32,
        source_mip_level: u32,
        destination: D,
        destination_top_left: [i32; 3],
        destination_bottom_right: [i32; 3],
        destination_base_array_layer: u32,
        destination_mip_level: u32,
        layer_count: u32,
        filter: Filter,
    ) -> Result<&mut Self, BlitImageError>
    where
        S: ImageAccess + Send + Sync + 'static,
        D: ImageAccess + Send + Sync + 'static,
    {
        unsafe {
            if !self.queue_family().supports_graphics() {
                return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
            }

            self.ensure_outside_render_pass()?;

            check_blit_image(
                self.device(),
                &source,
                source_top_left,
                source_bottom_right,
                source_base_array_layer,
                source_mip_level,
                &destination,
                destination_top_left,
                destination_bottom_right,
                destination_base_array_layer,
                destination_mip_level,
                layer_count,
                filter,
            )?;

            let blit = UnsafeCommandBufferBuilderImageBlit {
                // TODO:
                aspects: if source.has_color() {
                    ImageAspects {
                        color: true,
                        ..ImageAspects::none()
                    }
                } else {
                    unimplemented!()
                },
                source_mip_level,
                destination_mip_level,
                source_base_array_layer,
                destination_base_array_layer,
                layer_count,
                source_top_left,
                source_bottom_right,
                destination_top_left,
                destination_bottom_right,
            };

            self.inner.blit_image(
                source,
                ImageLayout::TransferSrcOptimal,
                destination, // TODO: let choose layout
                ImageLayout::TransferDstOptimal,
                iter::once(blit),
                filter,
            )?;
            Ok(self)
        }
    }

    /// Adds a command that clears all the layers and mipmap levels of a color image with a
    /// specific value.
    ///
    /// # Panic
    ///
    /// Panics if `color` is not a color value.
    ///
    pub fn clear_color_image<I>(
        &mut self,
        image: I,
        color: ClearValue,
    ) -> Result<&mut Self, ClearColorImageError>
    where
        I: ImageAccess + Send + Sync + 'static,
    {
        let layers = image.dimensions().array_layers();
        let levels = image.mipmap_levels();

        self.clear_color_image_dimensions(image, 0, layers, 0, levels, color)
    }

    /// Adds a command that clears a color image with a specific value.
    ///
    /// # Panic
    ///
    /// - Panics if `color` is not a color value.
    ///
    pub fn clear_color_image_dimensions<I>(
        &mut self,
        image: I,
        first_layer: u32,
        num_layers: u32,
        first_mipmap: u32,
        num_mipmaps: u32,
        color: ClearValue,
    ) -> Result<&mut Self, ClearColorImageError>
    where
        I: ImageAccess + Send + Sync + 'static,
    {
        unsafe {
            if !self.queue_family().supports_graphics() && !self.queue_family().supports_compute() {
                return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
            }

            self.ensure_outside_render_pass()?;
            check_clear_color_image(
                self.device(),
                &image,
                first_layer,
                num_layers,
                first_mipmap,
                num_mipmaps,
            )?;

            match color {
                ClearValue::Float(_) | ClearValue::Int(_) | ClearValue::Uint(_) => {}
                _ => panic!("The clear color is not a color value"),
            };

            let region = UnsafeCommandBufferBuilderColorImageClear {
                base_mip_level: first_mipmap,
                level_count: num_mipmaps,
                base_array_layer: first_layer,
                layer_count: num_layers,
            };

            // TODO: let choose layout
            self.inner.clear_color_image(
                image,
                ImageLayout::TransferDstOptimal,
                color,
                iter::once(region),
            )?;
            Ok(self)
        }
    }

    /// Adds a command that copies from a buffer to another.
    ///
    /// This command will copy from the source to the destination. If their size is not equal, then
    /// the amount of data copied is equal to the smallest of the two.
    #[inline]
    pub fn copy_buffer<S, D, T>(
        &mut self,
        source: S,
        destination: D,
    ) -> Result<&mut Self, CopyBufferError>
    where
        S: TypedBufferAccess<Content = T> + Send + Sync + 'static,
        D: TypedBufferAccess<Content = T> + Send + Sync + 'static,
        T: ?Sized,
    {
        unsafe {
            self.ensure_outside_render_pass()?;
            let infos = check_copy_buffer(self.device(), &source, &destination)?;
            self.inner
                .copy_buffer(source, destination, iter::once((0, 0, infos.copy_size)))?;
            Ok(self)
        }
    }

    /// Adds a command that copies a range from the source to the destination buffer.
    /// Panics if out of bounds.
    #[inline]
    pub fn copy_buffer_dimensions<S, D, T>(
        &mut self,
        source: S,
        source_offset: DeviceSize,
        destination: D,
        destination_offset: DeviceSize,
        count: DeviceSize,
    ) -> Result<&mut Self, CopyBufferError>
    where
        S: TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
        D: TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
    {
        self.ensure_outside_render_pass()?;

        let _infos = check_copy_buffer(self.device(), &source, &destination)?;
        debug_assert!(source_offset + count <= source.len());
        debug_assert!(destination_offset + count <= destination.len());

        let size = std::mem::size_of::<T>() as DeviceSize;
        unsafe {
            self.inner.copy_buffer(
                source,
                destination,
                iter::once((
                    source_offset * size,
                    destination_offset * size,
                    count * size,
                )),
            )?;
        }
        Ok(self)
    }

    /// Adds a command that copies from a buffer to an image.
    pub fn copy_buffer_to_image<S, D, Px>(
        &mut self,
        source: S,
        destination: D,
    ) -> Result<&mut Self, CopyBufferImageError>
    where
        S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
        D: ImageAccess + Send + Sync + 'static,
        Px: Pixel,
    {
        self.ensure_outside_render_pass()?;

        let dims = destination.dimensions().width_height_depth();
        self.copy_buffer_to_image_dimensions(source, destination, [0, 0, 0], dims, 0, 1, 0)
    }

    /// Adds a command that copies from a buffer to an image.
    pub fn copy_buffer_to_image_dimensions<S, D, Px>(
        &mut self,
        source: S,
        destination: D,
        offset: [u32; 3],
        size: [u32; 3],
        first_layer: u32,
        num_layers: u32,
        mipmap: u32,
    ) -> Result<&mut Self, CopyBufferImageError>
    where
        S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
        D: ImageAccess + Send + Sync + 'static,
        Px: Pixel,
    {
        unsafe {
            self.ensure_outside_render_pass()?;

            check_copy_buffer_image(
                self.device(),
                &source,
                &destination,
                CheckCopyBufferImageTy::BufferToImage,
                offset,
                size,
                first_layer,
                num_layers,
                mipmap,
            )?;

            let copy = UnsafeCommandBufferBuilderBufferImageCopy {
                buffer_offset: 0,
                buffer_row_length: 0,
                buffer_image_height: 0,
                image_aspect: if destination.has_color() {
                    ImageAspect::Color
                } else {
                    unimplemented!()
                },
                image_mip_level: mipmap,
                image_base_array_layer: first_layer,
                image_layer_count: num_layers,
                image_offset: [offset[0] as i32, offset[1] as i32, offset[2] as i32],
                image_extent: size,
            };

            self.inner.copy_buffer_to_image(
                source,
                destination,
                ImageLayout::TransferDstOptimal, // TODO: let choose layout
                iter::once(copy),
            )?;
            Ok(self)
        }
    }

    /// Adds a command that copies from an image to a buffer.
    // The data layout of the image on the gpu is opaque, as in, it is non of our business how the gpu stores the image.
    // This does not matter since the act of copying the image into a buffer converts it to linear form.
    pub fn copy_image_to_buffer<S, D, Px>(
        &mut self,
        source: S,
        destination: D,
    ) -> Result<&mut Self, CopyBufferImageError>
    where
        S: ImageAccess + Send + Sync + 'static,
        D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
        Px: Pixel,
    {
        self.ensure_outside_render_pass()?;

        let dims = source.dimensions().width_height_depth();
        self.copy_image_to_buffer_dimensions(source, destination, [0, 0, 0], dims, 0, 1, 0)
    }

    /// Adds a command that copies from an image to a buffer.
    pub fn copy_image_to_buffer_dimensions<S, D, Px>(
        &mut self,
        source: S,
        destination: D,
        offset: [u32; 3],
        size: [u32; 3],
        first_layer: u32,
        num_layers: u32,
        mipmap: u32,
    ) -> Result<&mut Self, CopyBufferImageError>
    where
        S: ImageAccess + Send + Sync + 'static,
        D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
        Px: Pixel,
    {
        unsafe {
            self.ensure_outside_render_pass()?;

            check_copy_buffer_image(
                self.device(),
                &destination,
                &source,
                CheckCopyBufferImageTy::ImageToBuffer,
                offset,
                size,
                first_layer,
                num_layers,
                mipmap,
            )?;

            let copy = UnsafeCommandBufferBuilderBufferImageCopy {
                buffer_offset: 0,
                buffer_row_length: 0,
                buffer_image_height: 0,
                // TODO: Allow the user to choose aspect
                image_aspect: if source.has_color() {
                    ImageAspect::Color
                } else if source.has_depth() {
                    ImageAspect::Depth
                } else if source.has_stencil() {
                    ImageAspect::Stencil
                } else {
                    unimplemented!()
                },
                image_mip_level: mipmap,
                image_base_array_layer: first_layer,
                image_layer_count: num_layers,
                image_offset: [offset[0] as i32, offset[1] as i32, offset[2] as i32],
                image_extent: size,
            };

            self.inner.copy_image_to_buffer(
                source,
                ImageLayout::TransferSrcOptimal,
                destination, // TODO: let choose layout
                iter::once(copy),
            )?;
            Ok(self)
        }
    }

    /// Open a command buffer debug label region.
    ///
    /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
    #[inline]
    pub fn debug_marker_begin(
        &mut self,
        name: &'static CStr,
        color: [f32; 4],
    ) -> Result<&mut Self, DebugMarkerError> {
        if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
            return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
        }

        check_debug_marker_color(color)?;

        unsafe {
            self.inner.debug_marker_begin(name.into(), color);
        }

        Ok(self)
    }

    /// Close a command buffer label region.
    ///
    /// Note: you need to open a command buffer label region first with `debug_marker_begin`.
    /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
    #[inline]
    pub fn debug_marker_end(&mut self) -> Result<&mut Self, DebugMarkerError> {
        if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
            return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
        }

        // TODO: validate that debug_marker_begin with same name was sent earlier

        unsafe {
            self.inner.debug_marker_end();
        }

        Ok(self)
    }

    /// Insert a label into a command buffer.
    ///
    /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
    #[inline]
    pub fn debug_marker_insert(
        &mut self,
        name: &'static CStr,
        color: [f32; 4],
    ) -> Result<&mut Self, DebugMarkerError> {
        if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
            return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
        }

        check_debug_marker_color(color)?;

        unsafe {
            self.inner.debug_marker_insert(name.into(), color);
        }

        Ok(self)
    }

    /// Perform a single compute operation using a compute pipeline.
    #[inline]
    pub fn dispatch<Cp, S, Pc>(
        &mut self,
        group_counts: [u32; 3],
        pipeline: Cp,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DispatchError>
    where
        Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            if !self.queue_family().supports_compute() {
                return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
            }

            self.ensure_outside_render_pass()?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
            check_dispatch(pipeline.device(), group_counts)?;

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_compute_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_compute(pipeline.clone());
            }

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Compute,
                pipeline.layout(),
                descriptor_sets,
            )?;

            self.inner.dispatch(group_counts);
            Ok(self)
        }
    }

    /// Perform multiple compute operations using a compute pipeline. One dispatch is performed for
    /// each `vulkano::command_buffer::DispatchIndirectCommand` struct in `indirect_buffer`.
    #[inline]
    pub fn dispatch_indirect<Inb, Cp, S, Pc>(
        &mut self,
        indirect_buffer: Inb,
        pipeline: Cp,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DispatchIndirectError>
    where
        Inb: BufferAccess
            + TypedBufferAccess<Content = [DispatchIndirectCommand]>
            + Send
            + Sync
            + 'static,
        Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            if !self.queue_family().supports_compute() {
                return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
            }

            self.ensure_outside_render_pass()?;
            check_indirect_buffer(self.device(), &indirect_buffer)?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_compute_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_compute(pipeline.clone());
            }

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Compute,
                pipeline.layout(),
                descriptor_sets,
            )?;

            self.inner.dispatch_indirect(indirect_buffer)?;
            Ok(self)
        }
    }

    /// Perform a single draw operation using a graphics pipeline.
    ///
    /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
    ///
    /// All data in `vertex_buffer` is used for the draw operation. To use only some data in the
    /// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
    #[inline]
    pub fn draw<V, Gp, S, Pc>(
        &mut self,
        pipeline: Gp,
        dynamic: &DynamicState,
        vertex_buffers: V,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DrawError>
    where
        Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            // TODO: must check that pipeline is compatible with render pass

            self.ensure_inside_render_pass_inline(&pipeline)?;
            check_dynamic_state_validity(&pipeline, dynamic)?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
            let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_graphics_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_graphics(pipeline.clone());
            }

            let dynamic = self.state_cacher.dynamic_state(dynamic);

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            set_state(&mut self.inner, &dynamic);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Graphics,
                pipeline.layout(),
                descriptor_sets,
            )?;
            bind_vertex_buffers(
                &mut self.inner,
                &mut self.state_cacher,
                vb_infos.vertex_buffers,
            )?;

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.draw(
                vb_infos.vertex_count as u32,
                vb_infos.instance_count as u32,
                0,
                0,
            );
            Ok(self)
        }
    }

    /// Perform multiple draw operations using a graphics pipeline.
    ///
    /// One draw is performed for each [`DrawIndirectCommand`] struct in `indirect_buffer`.
    /// The maximum number of draw commands in the buffer is limited by the
    /// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
    /// This limit is 1 unless the
    /// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
    /// enabled.
    ///
    /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input. It is
    /// used for every draw operation.
    ///
    /// All data in `vertex_buffer` is used for every draw operation. To use only some data in the
    /// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
    #[inline]
    pub fn draw_indirect<V, Gp, S, Pc, Inb>(
        &mut self,
        pipeline: Gp,
        dynamic: &DynamicState,
        vertex_buffers: V,
        indirect_buffer: Inb,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DrawIndirectError>
    where
        Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
        Inb: BufferAccess
            + TypedBufferAccess<Content = [DrawIndirectCommand]>
            + Send
            + Sync
            + 'static,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            // TODO: must check that pipeline is compatible with render pass

            self.ensure_inside_render_pass_inline(&pipeline)?;
            check_indirect_buffer(self.device(), &indirect_buffer)?;
            check_dynamic_state_validity(&pipeline, dynamic)?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
            let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;

            let requested = indirect_buffer.len() as u32;
            let limit = self
                .device()
                .physical_device()
                .properties()
                .max_draw_indirect_count;

            if requested > limit {
                return Err(
                    CheckIndirectBufferError::MaxDrawIndirectCountLimitExceeded {
                        limit,
                        requested,
                    }
                    .into(),
                );
            }

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_graphics_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_graphics(pipeline.clone());
            }

            let dynamic = self.state_cacher.dynamic_state(dynamic);

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            set_state(&mut self.inner, &dynamic);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Graphics,
                pipeline.layout(),
                descriptor_sets,
            )?;
            bind_vertex_buffers(
                &mut self.inner,
                &mut self.state_cacher,
                vb_infos.vertex_buffers,
            )?;

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.draw_indirect(
                indirect_buffer,
                requested,
                mem::size_of::<DrawIndirectCommand>() as u32,
            )?;
            Ok(self)
        }
    }

    /// Perform a single draw operation using a graphics pipeline, using an index buffer.
    ///
    /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
    /// `index_buffer` is a buffer containing indices into the vertex buffer that should be
    /// processed in order.
    ///
    /// All data in `vertex_buffer` and `index_buffer` is used for the draw operation. To use
    /// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
    #[inline]
    pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(
        &mut self,
        pipeline: Gp,
        dynamic: &DynamicState,
        vertex_buffers: V,
        index_buffer: Ib,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DrawIndexedError>
    where
        Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
        Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
        I: Index + 'static,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            // TODO: must check that pipeline is compatible with render pass

            self.ensure_inside_render_pass_inline(&pipeline)?;
            let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
            check_dynamic_state_validity(&pipeline, dynamic)?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
            let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_graphics_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_graphics(pipeline.clone());
            }

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_index_buffer(&index_buffer, I::ty())
            {
                self.inner.bind_index_buffer(index_buffer, I::ty())?;
            }

            let dynamic = self.state_cacher.dynamic_state(dynamic);

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            set_state(&mut self.inner, &dynamic);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Graphics,
                pipeline.layout(),
                descriptor_sets,
            )?;
            bind_vertex_buffers(
                &mut self.inner,
                &mut self.state_cacher,
                vb_infos.vertex_buffers,
            )?;
            // TODO: how to handle an index out of range of the vertex buffers?

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.draw_indexed(
                ib_infos.num_indices as u32,
                vb_infos.instance_count as u32,
                0,
                0,
                0,
            );
            Ok(self)
        }
    }

    /// Perform multiple draw operations using a graphics pipeline, using an index buffer.
    ///
    /// One draw is performed for each [`DrawIndirectCommand`] struct in `indirect_buffer`.
    /// The maximum number of draw commands in the buffer is limited by the
    /// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
    /// This limit is 1 unless the
    /// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
    /// enabled.
    ///
    /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
    /// `index_buffer` is a buffer containing indices into the vertex buffer that should be
    /// processed in order.
    ///
    /// All data in `vertex_buffer` and `index_buffer` is used for every draw operation. To use
    /// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
    #[inline]
    pub fn draw_indexed_indirect<V, Gp, S, Pc, Ib, Inb, I>(
        &mut self,
        pipeline: Gp,
        dynamic: &DynamicState,
        vertex_buffers: V,
        index_buffer: Ib,
        indirect_buffer: Inb,
        descriptor_sets: S,
        push_constants: Pc,
    ) -> Result<&mut Self, DrawIndexedIndirectError>
    where
        Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
        S: DescriptorSetsCollection,
        Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
        Inb: BufferAccess
            + TypedBufferAccess<Content = [DrawIndexedIndirectCommand]>
            + Send
            + Sync
            + 'static,
        I: Index + 'static,
    {
        let descriptor_sets = descriptor_sets.into_vec();

        unsafe {
            // TODO: must check that pipeline is compatible with render pass

            self.ensure_inside_render_pass_inline(&pipeline)?;
            let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
            check_indirect_buffer(self.device(), &indirect_buffer)?;
            check_dynamic_state_validity(&pipeline, dynamic)?;
            check_push_constants_validity(pipeline.layout(), &push_constants)?;
            check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
            let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;

            let requested = indirect_buffer.len() as u32;
            let limit = self
                .device()
                .physical_device()
                .properties()
                .max_draw_indirect_count;

            if requested > limit {
                return Err(
                    CheckIndirectBufferError::MaxDrawIndirectCountLimitExceeded {
                        limit,
                        requested,
                    }
                    .into(),
                );
            }

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_graphics_pipeline(&pipeline)
            {
                self.inner.bind_pipeline_graphics(pipeline.clone());
            }

            if let StateCacherOutcome::NeedChange =
                self.state_cacher.bind_index_buffer(&index_buffer, I::ty())
            {
                self.inner.bind_index_buffer(index_buffer, I::ty())?;
            }

            let dynamic = self.state_cacher.dynamic_state(dynamic);

            set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
            set_state(&mut self.inner, &dynamic);
            bind_descriptor_sets(
                &mut self.inner,
                &mut self.state_cacher,
                PipelineBindPoint::Graphics,
                pipeline.layout(),
                descriptor_sets,
            )?;
            bind_vertex_buffers(
                &mut self.inner,
                &mut self.state_cacher,
                vb_infos.vertex_buffers,
            )?;

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.draw_indexed_indirect(
                indirect_buffer,
                requested,
                mem::size_of::<DrawIndexedIndirectCommand>() as u32,
            )?;
            Ok(self)
        }
    }

    /// Adds a command that writes the content of a buffer.
    ///
    /// This function is similar to the `memset` function in C. The `data` parameter is a number
    /// that will be repeatedly written through the entire buffer.
    ///
    /// > **Note**: This function is technically safe because buffers can only contain integers or
    /// > floating point numbers, which are always valid whatever their memory representation is.
    /// > But unless your buffer actually contains only 32-bits integers, you are encouraged to use
    /// > this function only for zeroing the content of a buffer by passing `0` for the data.
    // TODO: not safe because of signalling NaNs
    #[inline]
    pub fn fill_buffer<B>(&mut self, buffer: B, data: u32) -> Result<&mut Self, FillBufferError>
    where
        B: BufferAccess + Send + Sync + 'static,
    {
        unsafe {
            self.ensure_outside_render_pass()?;
            check_fill_buffer(self.device(), &buffer)?;
            self.inner.fill_buffer(buffer, data);
            Ok(self)
        }
    }

    /// Adds a command that writes data to a buffer.
    ///
    /// If `data` is larger than the buffer, only the part of `data` that fits is written. If the
    /// buffer is larger than `data`, only the start of the buffer is written.
    #[inline]
    pub fn update_buffer<B, D, Dd>(
        &mut self,
        buffer: B,
        data: Dd,
    ) -> Result<&mut Self, UpdateBufferError>
    where
        B: TypedBufferAccess<Content = D> + Send + Sync + 'static,
        D: ?Sized,
        Dd: SafeDeref<Target = D> + Send + Sync + 'static,
    {
        unsafe {
            self.ensure_outside_render_pass()?;
            check_update_buffer(self.device(), &buffer, data.deref())?;

            let size_of_data = mem::size_of_val(data.deref()) as DeviceSize;
            if buffer.size() >= size_of_data {
                self.inner.update_buffer(buffer, data);
            } else {
                unimplemented!() // TODO:
                                 //self.inner.update_buffer(buffer.slice(0 .. size_of_data), data);
            }

            Ok(self)
        }
    }

    /// Adds a command that begins a query.
    ///
    /// The query will be active until [`end_query`](Self::end_query) is called for the same query.
    ///
    /// # Safety
    /// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
    pub unsafe fn begin_query(
        &mut self,
        query_pool: Arc<QueryPool>,
        query: u32,
        flags: QueryControlFlags,
    ) -> Result<&mut Self, BeginQueryError> {
        check_begin_query(self.device(), &query_pool, query, flags)?;

        match query_pool.ty() {
            QueryType::Occlusion => {
                if !self.queue_family().supports_graphics() {
                    return Err(
                        AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into(),
                    );
                }
            }
            QueryType::PipelineStatistics(flags) => {
                if flags.is_compute() && !self.queue_family().supports_compute()
                    || flags.is_graphics() && !self.queue_family().supports_graphics()
                {
                    return Err(
                        AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into(),
                    );
                }
            }
            QueryType::Timestamp => unreachable!(),
        }

        let ty = query_pool.ty();
        let raw_ty = ty.into();
        let raw_query_pool = query_pool.internal_object();
        if self.query_state.contains_key(&raw_ty) {
            return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
        }

        // TODO: validity checks
        self.inner.begin_query(query_pool, query, flags);
        self.query_state.insert(
            raw_ty,
            QueryState {
                query_pool: raw_query_pool,
                query,
                ty,
                flags,
                in_subpass: self.render_pass_state.is_some(),
            },
        );

        Ok(self)
    }

    /// Adds a command that ends an active query.
    pub fn end_query(
        &mut self,
        query_pool: Arc<QueryPool>,
        query: u32,
    ) -> Result<&mut Self, EndQueryError> {
        unsafe {
            check_end_query(self.device(), &query_pool, query)?;

            let raw_ty = query_pool.ty().into();
            let raw_query_pool = query_pool.internal_object();
            if !self.query_state.get(&raw_ty).map_or(false, |state| {
                state.query_pool == raw_query_pool && state.query == query
            }) {
                return Err(AutoCommandBufferBuilderContextError::QueryNotActive.into());
            }

            self.inner.end_query(query_pool, query);
            self.query_state.remove(&raw_ty);
        }

        Ok(self)
    }

    /// Adds a command that writes a timestamp to a timestamp query.
    ///
    /// # Safety
    /// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
    pub unsafe fn write_timestamp(
        &mut self,
        query_pool: Arc<QueryPool>,
        query: u32,
        stage: PipelineStage,
    ) -> Result<&mut Self, WriteTimestampError> {
        check_write_timestamp(
            self.device(),
            self.queue_family(),
            &query_pool,
            query,
            stage,
        )?;

        if !(self.queue_family().supports_graphics()
            || self.queue_family().supports_compute()
            || self.queue_family().explicitly_supports_transfers())
        {
            return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
        }

        // TODO: validity checks
        self.inner.write_timestamp(query_pool, query, stage);

        Ok(self)
    }

    /// Adds a command that copies the results of a range of queries to a buffer on the GPU.
    ///
    /// [`query_pool.ty().result_size()`](crate::query::QueryType::result_size) elements
    /// will be written for each query in the range, plus 1 extra element per query if
    /// [`QueryResultFlags::with_availability`] is enabled.
    /// The provided buffer must be large enough to hold the data.
    ///
    /// See also [`get_results`](crate::query::QueriesRange::get_results).
    pub fn copy_query_pool_results<D, T>(
        &mut self,
        query_pool: Arc<QueryPool>,
        queries: Range<u32>,
        destination: D,
        flags: QueryResultFlags,
    ) -> Result<&mut Self, CopyQueryPoolResultsError>
    where
        D: BufferAccess + TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
        T: QueryResultElement,
    {
        unsafe {
            self.ensure_outside_render_pass()?;
            let stride = check_copy_query_pool_results(
                self.device(),
                &query_pool,
                queries.clone(),
                &destination,
                flags,
            )?;
            self.inner
                .copy_query_pool_results(query_pool, queries, destination, stride, flags)?;
        }

        Ok(self)
    }

    /// Adds a command to reset a range of queries on a query pool.
    ///
    /// The affected queries will be marked as "unavailable" after this command runs, and will no
    /// longer return any results. They will be ready to have new results recorded for them.
    ///
    /// # Safety
    /// The queries in the specified range must not be active in another command buffer.
    pub unsafe fn reset_query_pool(
        &mut self,
        query_pool: Arc<QueryPool>,
        queries: Range<u32>,
    ) -> Result<&mut Self, ResetQueryPoolError> {
        self.ensure_outside_render_pass()?;
        check_reset_query_pool(self.device(), &query_pool, queries.clone())?;

        let raw_query_pool = query_pool.internal_object();
        if self
            .query_state
            .values()
            .any(|state| state.query_pool == raw_query_pool && queries.contains(&state.query))
        {
            return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
        }

        // TODO: validity checks
        // Do other command buffers actually matter here? Not sure on the Vulkan spec.
        self.inner.reset_query_pool(query_pool, queries);

        Ok(self)
    }
}

/// Commands that can only be executed on primary command buffers
impl<P> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<P::Alloc>, P>
where
    P: CommandPoolBuilderAlloc,
{
    /// Adds a command that enters a render pass.
    ///
    /// If `contents` is `SubpassContents::SecondaryCommandBuffers`, then you will only be able to
    /// add secondary command buffers while you're inside the first subpass of the render pass.
    /// If it is `SubpassContents::Inline`, you will only be able to add inline draw commands and
    /// not secondary command buffers.
    ///
    /// C must contain exactly one clear value for each attachment in the framebuffer.
    ///
    /// You must call this before you can add draw commands.
    #[inline]
    pub fn begin_render_pass<F, I>(
        &mut self,
        framebuffer: F,
        contents: SubpassContents,
        clear_values: I,
    ) -> Result<&mut Self, BeginRenderPassError>
    where
        F: FramebufferAbstract + Clone + Send + Sync + 'static,
        I: IntoIterator<Item = ClearValue>,
    {
        unsafe {
            if !self.queue_family().supports_graphics() {
                return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
            }

            self.ensure_outside_render_pass()?;

            let clear_values = framebuffer
                .render_pass()
                .desc()
                .convert_clear_values(clear_values);
            let clear_values = clear_values.collect::<Vec<_>>().into_iter(); // TODO: necessary for Send + Sync ; needs an API rework of convert_clear_values
            let mut clear_values_copy = clear_values.clone().enumerate(); // TODO: Proper errors for clear value errors instead of panics

            for (atch_i, atch_desc) in framebuffer
                .render_pass()
                .desc()
                .attachments()
                .into_iter()
                .enumerate()
            {
                match clear_values_copy.next() {
                    Some((clear_i, clear_value)) => {
                        if atch_desc.load == LoadOp::Clear {
                            match clear_value {
                                ClearValue::None => panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: None",
                                    clear_i, atch_i, atch_desc.format.ty()),
                                ClearValue::Float(_) => if atch_desc.format.ty() != FormatTy::Float {
                                   panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Float",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                                ClearValue::Int(_) => if atch_desc.format.ty() != FormatTy::Sint {
                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Int",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                                ClearValue::Uint(_) => if atch_desc.format.ty() != FormatTy::Uint {
                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Uint",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                                ClearValue::Depth(_) => if atch_desc.format.ty() != FormatTy::Depth {
                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Depth",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                                ClearValue::Stencil(_) => if atch_desc.format.ty() != FormatTy::Stencil {
                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Stencil",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                                ClearValue::DepthStencil(_) => if atch_desc.format.ty() != FormatTy::DepthStencil {
                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: DepthStencil",
                                       clear_i, atch_i, atch_desc.format.ty());
                                }
                            }
                        } else {
                            if clear_value != ClearValue::None {
                                panic!("Bad ClearValue! index: {}, attachment index: {}, expected: None, got: {:?}",
                                   clear_i, atch_i, clear_value);
                            }
                        }
                    }
                    None => panic!("Not enough clear values"),
                }
            }

            if clear_values_copy.count() != 0 {
                panic!("Too many clear values")
            }

            if let Some(multiview_desc) = framebuffer.render_pass().desc().multiview() {
                // When multiview is enabled, at the beginning of each subpass all non-render pass state is undefined
                self.state_cacher.invalidate();

                // ensure that the framebuffer is compatible with the render pass multiview configuration
                if multiview_desc
                    .view_masks
                    .iter()
                    .chain(multiview_desc.correlation_masks.iter())
                    .map(|&mask| 32 - mask.leading_zeros()) // calculates the highest used layer index of the mask
                    .any(|highest_used_layer| highest_used_layer > framebuffer.layers())
                {
                    panic!("A multiview mask references more layers than exist in the framebuffer");
                }
            }

            let framebuffer_object = FramebufferAbstract::inner(&framebuffer).internal_object();
            self.inner
                .begin_render_pass(framebuffer.clone(), contents, clear_values)?;
            self.render_pass_state = Some(RenderPassState {
                subpass: (framebuffer.render_pass().clone(), 0),
                contents,
                framebuffer: framebuffer_object,
            });
            Ok(self)
        }
    }

    /// Adds a command that ends the current render pass.
    ///
    /// This must be called after you went through all the subpasses and before you can build
    /// the command buffer or add further commands.
    #[inline]
    pub fn end_render_pass(&mut self) -> Result<&mut Self, AutoCommandBufferBuilderContextError> {
        unsafe {
            if let Some(render_pass_state) = self.render_pass_state.as_ref() {
                let (ref rp, index) = render_pass_state.subpass;

                if rp.desc().subpasses().len() as u32 != index + 1 {
                    return Err(AutoCommandBufferBuilderContextError::NumSubpassesMismatch {
                        actual: rp.desc().subpasses().len() as u32,
                        current: index,
                    });
                }
            } else {
                return Err(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass);
            }

            if self.query_state.values().any(|state| state.in_subpass) {
                return Err(AutoCommandBufferBuilderContextError::QueryIsActive);
            }

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.end_render_pass();
            self.render_pass_state = None;
            Ok(self)
        }
    }

    /// Adds a command that executes a secondary command buffer.
    ///
    /// If the `flags` that `command_buffer` was created with are more restrictive than those of
    /// `self`, then `self` will be restricted to match. E.g. executing a secondary command buffer
    /// with `Flags::OneTimeSubmit` will set `self`'s flags to `Flags::OneTimeSubmit` also.
    pub fn execute_commands<C>(
        &mut self,
        command_buffer: C,
    ) -> Result<&mut Self, ExecuteCommandsError>
    where
        C: SecondaryCommandBuffer + Send + Sync + 'static,
    {
        self.check_command_buffer(&command_buffer)?;
        let secondary_usage = command_buffer.inner().usage();

        unsafe {
            let mut builder = self.inner.execute_commands();
            builder.add(command_buffer);
            builder.submit()?;
        }

        // Secondary command buffer could leave the primary in any state.
        self.state_cacher.invalidate();

        // If the secondary is non-concurrent or one-time use, that restricts the primary as well.
        self.usage = std::cmp::min(self.usage, secondary_usage);

        Ok(self)
    }

    /// Adds a command that multiple secondary command buffers in a vector.
    ///
    /// This requires that the secondary command buffers do not have resource conflicts; an error
    /// will be returned if there are any. Use `execute_commands` if you want to ensure that
    /// resource conflicts are automatically resolved.
    // TODO ^ would be nice if this just worked without errors
    pub fn execute_commands_from_vec<C>(
        &mut self,
        command_buffers: Vec<C>,
    ) -> Result<&mut Self, ExecuteCommandsError>
    where
        C: SecondaryCommandBuffer + Send + Sync + 'static,
    {
        for command_buffer in &command_buffers {
            self.check_command_buffer(command_buffer)?;
        }

        let mut secondary_usage = CommandBufferUsage::SimultaneousUse; // Most permissive usage
        unsafe {
            let mut builder = self.inner.execute_commands();
            for command_buffer in command_buffers {
                secondary_usage = std::cmp::min(secondary_usage, command_buffer.inner().usage());
                builder.add(command_buffer);
            }
            builder.submit()?;
        }

        // Secondary command buffer could leave the primary in any state.
        self.state_cacher.invalidate();

        // If the secondary is non-concurrent or one-time use, that restricts the primary as well.
        self.usage = std::cmp::min(self.usage, secondary_usage);

        Ok(self)
    }

    // Helper function for execute_commands
    fn check_command_buffer<C>(
        &self,
        command_buffer: &C,
    ) -> Result<(), AutoCommandBufferBuilderContextError>
    where
        C: SecondaryCommandBuffer + Send + Sync + 'static,
    {
        if let Some(render_pass) = command_buffer.inheritance().render_pass {
            self.ensure_inside_render_pass_secondary(&render_pass)?;
        } else {
            self.ensure_outside_render_pass()?;
        }

        for state in self.query_state.values() {
            match state.ty {
                QueryType::Occlusion => match command_buffer.inheritance().occlusion_query {
                    Some(inherited_flags) => {
                        let inherited_flags = ash::vk::QueryControlFlags::from(inherited_flags);
                        let state_flags = ash::vk::QueryControlFlags::from(state.flags);

                        if inherited_flags & state_flags != state_flags {
                            return Err(AutoCommandBufferBuilderContextError::QueryNotInherited);
                        }
                    }
                    None => return Err(AutoCommandBufferBuilderContextError::QueryNotInherited),
                },
                QueryType::PipelineStatistics(state_flags) => {
                    let inherited_flags = command_buffer.inheritance().query_statistics_flags;
                    let inherited_flags =
                        ash::vk::QueryPipelineStatisticFlags::from(inherited_flags);
                    let state_flags = ash::vk::QueryPipelineStatisticFlags::from(state_flags);

                    if inherited_flags & state_flags != state_flags {
                        return Err(AutoCommandBufferBuilderContextError::QueryNotInherited);
                    }
                }
                _ => (),
            }
        }

        Ok(())
    }

    #[inline]
    fn ensure_inside_render_pass_secondary(
        &self,
        render_pass: &CommandBufferInheritanceRenderPass<&dyn FramebufferAbstract>,
    ) -> Result<(), AutoCommandBufferBuilderContextError> {
        let render_pass_state = self
            .render_pass_state
            .as_ref()
            .ok_or(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass)?;

        if render_pass_state.contents != SubpassContents::SecondaryCommandBuffers {
            return Err(AutoCommandBufferBuilderContextError::WrongSubpassType);
        }

        // Subpasses must be the same.
        if render_pass.subpass.index() != render_pass_state.subpass.1 {
            return Err(AutoCommandBufferBuilderContextError::WrongSubpassIndex);
        }

        // Render passes must be compatible.
        if !render_pass
            .subpass
            .render_pass()
            .desc()
            .is_compatible_with_desc(render_pass_state.subpass.0.desc())
        {
            return Err(AutoCommandBufferBuilderContextError::IncompatibleRenderPass);
        }

        // Framebuffer, if present on the secondary command buffer, must be the
        // same as the one in the current render pass.
        if let Some(framebuffer) = render_pass.framebuffer {
            if FramebufferAbstract::inner(framebuffer).internal_object()
                != render_pass_state.framebuffer
            {
                return Err(AutoCommandBufferBuilderContextError::IncompatibleFramebuffer);
            }
        }

        Ok(())
    }

    /// Adds a command that jumps to the next subpass of the current render pass.
    #[inline]
    pub fn next_subpass(
        &mut self,
        contents: SubpassContents,
    ) -> Result<&mut Self, AutoCommandBufferBuilderContextError> {
        unsafe {
            if let Some(render_pass_state) = self.render_pass_state.as_mut() {
                let (ref rp, ref mut index) = render_pass_state.subpass;

                if *index + 1 >= rp.desc().subpasses().len() as u32 {
                    return Err(AutoCommandBufferBuilderContextError::NumSubpassesMismatch {
                        actual: rp.desc().subpasses().len() as u32,
                        current: *index,
                    });
                } else {
                    *index += 1;
                    render_pass_state.contents = contents;
                }

                if let Some(multiview) = rp.desc().multiview() {
                    // When multiview is enabled, at the beginning of each subpass all non-render pass state is undefined
                    self.state_cacher.invalidate();
                }
            } else {
                return Err(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass);
            }

            if self.query_state.values().any(|state| state.in_subpass) {
                return Err(AutoCommandBufferBuilderContextError::QueryIsActive);
            }

            debug_assert!(self.queue_family().supports_graphics());

            self.inner.next_subpass(contents);
            Ok(self)
        }
    }
}

impl<P> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<P::Alloc>, P> where
    P: CommandPoolBuilderAlloc
{
}

unsafe impl<L, P> DeviceOwned for AutoCommandBufferBuilder<L, P> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.inner.device()
    }
}

// Shortcut function to set the push constants.
unsafe fn set_push_constants<Pc>(
    destination: &mut SyncCommandBufferBuilder,
    pipeline_layout: &Arc<PipelineLayout>,
    push_constants: Pc,
) {
    for range in pipeline_layout.push_constant_ranges() {
        debug_assert_eq!(range.offset % 4, 0);
        debug_assert_eq!(range.size % 4, 0);

        let data = slice::from_raw_parts(
            (&push_constants as *const Pc as *const u8).offset(range.offset as isize),
            range.size as usize,
        );

        destination.push_constants::<[u8]>(
            pipeline_layout.clone(),
            range.stages,
            range.offset as u32,
            range.size as u32,
            data,
        );
    }
}

// Shortcut function to change the state of the pipeline.
unsafe fn set_state(destination: &mut SyncCommandBufferBuilder, dynamic: &DynamicState) {
    if let Some(line_width) = dynamic.line_width {
        destination.set_line_width(line_width);
    }

    if let Some(ref viewports) = dynamic.viewports {
        destination.set_viewport(0, viewports.iter().cloned().collect::<Vec<_>>().into_iter());
        // TODO: don't collect
    }

    if let Some(ref scissors) = dynamic.scissors {
        destination.set_scissor(0, scissors.iter().cloned().collect::<Vec<_>>().into_iter());
        // TODO: don't collect
    }

    if let Some(compare_mask) = dynamic.compare_mask {
        destination.set_stencil_compare_mask(StencilFaces::Front, compare_mask.front);
        destination.set_stencil_compare_mask(StencilFaces::Back, compare_mask.back);
    }

    if let Some(write_mask) = dynamic.write_mask {
        destination.set_stencil_write_mask(StencilFaces::Front, write_mask.front);
        destination.set_stencil_write_mask(StencilFaces::Back, write_mask.back);
    }

    if let Some(reference) = dynamic.reference {
        destination.set_stencil_reference(StencilFaces::Front, reference.front);
        destination.set_stencil_reference(StencilFaces::Back, reference.back);
    }
}

// Shortcut function to bind vertex buffers.
unsafe fn bind_vertex_buffers(
    destination: &mut SyncCommandBufferBuilder,
    state_cacher: &mut StateCacher,
    vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>,
) -> Result<(), SyncCommandBufferBuilderError> {
    let binding_range = {
        let mut compare = state_cacher.bind_vertex_buffers();
        for vb in vertex_buffers.iter() {
            compare.add(vb);
        }
        match compare.compare() {
            Some(r) => r,
            None => return Ok(()),
        }
    };

    let first_binding = binding_range.start;
    let num_bindings = binding_range.end - binding_range.start;

    let mut binder = destination.bind_vertex_buffers();
    for vb in vertex_buffers
        .into_iter()
        .skip(first_binding as usize)
        .take(num_bindings as usize)
    {
        binder.add(vb);
    }
    binder.submit(first_binding)?;
    Ok(())
}

unsafe fn bind_descriptor_sets(
    destination: &mut SyncCommandBufferBuilder,
    state_cacher: &mut StateCacher,
    pipeline_bind_point: PipelineBindPoint,
    pipeline_layout: &Arc<PipelineLayout>,
    descriptor_sets: Vec<DescriptorSetWithOffsets>,
) -> Result<(), SyncCommandBufferBuilderError> {
    let first_binding = {
        let mut compare = state_cacher.bind_descriptor_sets(pipeline_bind_point);
        for descriptor_set in descriptor_sets.iter() {
            compare.add(descriptor_set);
        }
        compare.compare()
    };

    let first_binding = match first_binding {
        None => return Ok(()),
        Some(fb) => fb,
    };

    let mut sets_binder = destination.bind_descriptor_sets();
    for set in descriptor_sets.into_iter().skip(first_binding as usize) {
        sets_binder.add(set);
    }
    sets_binder.submit(pipeline_bind_point, pipeline_layout.clone(), first_binding)?;
    Ok(())
}

pub struct PrimaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
    inner: SyncCommandBuffer,
    pool_alloc: P, // Safety: must be dropped after `inner`

    // Tracks usage of the command buffer on the GPU.
    submit_state: SubmitState,
}

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

unsafe impl<P> PrimaryCommandBuffer for PrimaryAutoCommandBuffer<P> {
    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer {
        self.inner.as_ref()
    }

    #[inline]
    fn lock_submit(
        &self,
        future: &dyn GpuFuture,
        queue: &Queue,
    ) -> Result<(), CommandBufferExecError> {
        match self.submit_state {
            SubmitState::OneTime {
                ref already_submitted,
            } => {
                let was_already_submitted = already_submitted.swap(true, Ordering::SeqCst);
                if was_already_submitted {
                    return Err(CommandBufferExecError::OneTimeSubmitAlreadySubmitted);
                }
            }
            SubmitState::ExclusiveUse { ref in_use } => {
                let already_in_use = in_use.swap(true, Ordering::SeqCst);
                if already_in_use {
                    return Err(CommandBufferExecError::ExclusiveAlreadyInUse);
                }
            }
            SubmitState::Concurrent => (),
        };

        let err = match self.inner.lock_submit(future, queue) {
            Ok(()) => return Ok(()),
            Err(err) => err,
        };

        // If `self.inner.lock_submit()` failed, we revert action.
        match self.submit_state {
            SubmitState::OneTime {
                ref already_submitted,
            } => {
                already_submitted.store(false, Ordering::SeqCst);
            }
            SubmitState::ExclusiveUse { ref in_use } => {
                in_use.store(false, Ordering::SeqCst);
            }
            SubmitState::Concurrent => (),
        };

        Err(err)
    }

    #[inline]
    unsafe fn unlock(&self) {
        // Because of panic safety, we unlock the inner command buffer first.
        self.inner.unlock();

        match self.submit_state {
            SubmitState::OneTime {
                ref already_submitted,
            } => {
                debug_assert!(already_submitted.load(Ordering::SeqCst));
            }
            SubmitState::ExclusiveUse { ref in_use } => {
                let old_val = in_use.swap(false, Ordering::SeqCst);
                debug_assert!(old_val);
            }
            SubmitState::Concurrent => (),
        };
    }

    #[inline]
    fn check_buffer_access(
        &self,
        buffer: &dyn BufferAccess,
        exclusive: bool,
        queue: &Queue,
    ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
        self.inner.check_buffer_access(buffer, exclusive, queue)
    }

    #[inline]
    fn check_image_access(
        &self,
        image: &dyn ImageAccess,
        layout: ImageLayout,
        exclusive: bool,
        queue: &Queue,
    ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
        self.inner
            .check_image_access(image, layout, exclusive, queue)
    }
}

pub struct SecondaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
    inner: SyncCommandBuffer,
    pool_alloc: P, // Safety: must be dropped after `inner`
    inheritance: CommandBufferInheritance<Box<dyn FramebufferAbstract + Send + Sync>>,

    // Tracks usage of the command buffer on the GPU.
    submit_state: SubmitState,
}

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

unsafe impl<P> SecondaryCommandBuffer for SecondaryAutoCommandBuffer<P> {
    #[inline]
    fn inner(&self) -> &UnsafeCommandBuffer {
        self.inner.as_ref()
    }

    #[inline]
    fn lock_record(&self) -> Result<(), CommandBufferExecError> {
        match self.submit_state {
            SubmitState::OneTime {
                ref already_submitted,
            } => {
                let was_already_submitted = already_submitted.swap(true, Ordering::SeqCst);
                if was_already_submitted {
                    return Err(CommandBufferExecError::OneTimeSubmitAlreadySubmitted);
                }
            }
            SubmitState::ExclusiveUse { ref in_use } => {
                let already_in_use = in_use.swap(true, Ordering::SeqCst);
                if already_in_use {
                    return Err(CommandBufferExecError::ExclusiveAlreadyInUse);
                }
            }
            SubmitState::Concurrent => (),
        };

        Ok(())
    }

    #[inline]
    unsafe fn unlock(&self) {
        match self.submit_state {
            SubmitState::OneTime {
                ref already_submitted,
            } => {
                debug_assert!(already_submitted.load(Ordering::SeqCst));
            }
            SubmitState::ExclusiveUse { ref in_use } => {
                let old_val = in_use.swap(false, Ordering::SeqCst);
                debug_assert!(old_val);
            }
            SubmitState::Concurrent => (),
        };
    }

    fn inheritance(&self) -> CommandBufferInheritance<&dyn FramebufferAbstract> {
        CommandBufferInheritance {
            render_pass: self.inheritance.render_pass.as_ref().map(
                |CommandBufferInheritanceRenderPass {
                     subpass,
                     framebuffer,
                 }| {
                    CommandBufferInheritanceRenderPass {
                        subpass: subpass.clone(),
                        framebuffer: framebuffer.as_ref().map(|f| f.as_ref() as &_),
                    }
                },
            ),
            occlusion_query: self.inheritance.occlusion_query,
            query_statistics_flags: self.inheritance.query_statistics_flags,
        }
    }

    #[inline]
    fn num_buffers(&self) -> usize {
        self.inner.num_buffers()
    }

    #[inline]
    fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, PipelineMemoryAccess)> {
        self.inner.buffer(index)
    }

    #[inline]
    fn num_images(&self) -> usize {
        self.inner.num_images()
    }

    #[inline]
    fn image(
        &self,
        index: usize,
    ) -> Option<(
        &dyn ImageAccess,
        PipelineMemoryAccess,
        ImageLayout,
        ImageLayout,
        ImageUninitializedSafe,
    )> {
        self.inner.image(index)
    }
}

// Whether the command buffer can be submitted.
#[derive(Debug)]
enum SubmitState {
    // The command buffer was created with the "SimultaneousUse" flag. Can always be submitted at
    // any time.
    Concurrent,

    // The command buffer can only be submitted once simultaneously.
    ExclusiveUse {
        // True if the command buffer is current in use by the GPU.
        in_use: AtomicBool,
    },

    // The command buffer can only ever be submitted once.
    OneTime {
        // True if the command buffer has already been submitted once and can be no longer be
        // submitted.
        already_submitted: AtomicBool,
    },
}

macro_rules! err_gen {
    ($name:ident { $($err:ident,)+ }) => (
        #[derive(Debug, Clone)]
        pub enum $name {
            $(
                $err($err),
            )+
        }

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

        impl fmt::Display for $name {
            #[inline]
            fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
                write!(fmt, "{}", match *self {
                    $(
                        $name::$err(_) => {
                            concat!("a ", stringify!($err))
                        }
                    )+
                })
            }
        }

        $(
            impl From<$err> for $name {
                #[inline]
                fn from(err: $err) -> $name {
                    $name::$err(err)
                }
            }
        )+
    );
}

err_gen!(BuildError {
    AutoCommandBufferBuilderContextError,
    OomError,
});

err_gen!(BeginRenderPassError {
    AutoCommandBufferBuilderContextError,
    SyncCommandBufferBuilderError,
});

err_gen!(CopyImageError {
    AutoCommandBufferBuilderContextError,
    CheckCopyImageError,
    SyncCommandBufferBuilderError,
});

err_gen!(BlitImageError {
    AutoCommandBufferBuilderContextError,
    CheckBlitImageError,
    SyncCommandBufferBuilderError,
});

err_gen!(ClearColorImageError {
    AutoCommandBufferBuilderContextError,
    CheckClearColorImageError,
    SyncCommandBufferBuilderError,
});

err_gen!(CopyBufferError {
    AutoCommandBufferBuilderContextError,
    CheckCopyBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(CopyBufferImageError {
    AutoCommandBufferBuilderContextError,
    CheckCopyBufferImageError,
    SyncCommandBufferBuilderError,
});

err_gen!(CopyQueryPoolResultsError {
    AutoCommandBufferBuilderContextError,
    CheckCopyQueryPoolResultsError,
    SyncCommandBufferBuilderError,
});

err_gen!(FillBufferError {
    AutoCommandBufferBuilderContextError,
    CheckFillBufferError,
});

err_gen!(DebugMarkerError {
    AutoCommandBufferBuilderContextError,
    CheckColorError,
});

err_gen!(DispatchError {
    AutoCommandBufferBuilderContextError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckDispatchError,
    SyncCommandBufferBuilderError,
});

err_gen!(DispatchIndirectError {
    AutoCommandBufferBuilderContextError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckIndirectBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(DrawError {
    AutoCommandBufferBuilderContextError,
    CheckDynamicStateValidityError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckVertexBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(DrawIndexedError {
    AutoCommandBufferBuilderContextError,
    CheckDynamicStateValidityError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckVertexBufferError,
    CheckIndexBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(DrawIndirectError {
    AutoCommandBufferBuilderContextError,
    CheckDynamicStateValidityError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckVertexBufferError,
    CheckIndirectBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(DrawIndexedIndirectError {
    AutoCommandBufferBuilderContextError,
    CheckDynamicStateValidityError,
    CheckPushConstantsValidityError,
    CheckDescriptorSetsValidityError,
    CheckVertexBufferError,
    CheckIndexBufferError,
    CheckIndirectBufferError,
    SyncCommandBufferBuilderError,
});

err_gen!(ExecuteCommandsError {
    AutoCommandBufferBuilderContextError,
    SyncCommandBufferBuilderError,
});

err_gen!(BeginQueryError {
    AutoCommandBufferBuilderContextError,
    CheckBeginQueryError,
});

err_gen!(EndQueryError {
    AutoCommandBufferBuilderContextError,
    CheckEndQueryError,
});

err_gen!(WriteTimestampError {
    AutoCommandBufferBuilderContextError,
    CheckWriteTimestampError,
});

err_gen!(ResetQueryPoolError {
    AutoCommandBufferBuilderContextError,
    CheckResetQueryPoolError,
});

err_gen!(UpdateBufferError {
    AutoCommandBufferBuilderContextError,
    CheckUpdateBufferError,
});

#[derive(Debug, Copy, Clone)]
pub enum AutoCommandBufferBuilderContextError {
    /// Operation forbidden inside of a render pass.
    ForbiddenInsideRenderPass,
    /// Operation forbidden outside of a render pass.
    ForbiddenOutsideRenderPass,
    /// Tried to use a secondary command buffer with a specified framebuffer that is
    /// incompatible with the current framebuffer.
    IncompatibleFramebuffer,
    /// Tried to use a graphics pipeline or secondary command buffer whose render pass
    /// is incompatible with the current render pass.
    IncompatibleRenderPass,
    /// The queue family doesn't allow this operation.
    NotSupportedByQueueFamily,
    /// Tried to end a render pass with subpasses remaining, or tried to go to next subpass with no
    /// subpass remaining.
    NumSubpassesMismatch {
        /// Actual number of subpasses in the current render pass.
        actual: u32,
        /// Current subpass index before the failing command.
        current: u32,
    },
    /// A query is active that conflicts with the current operation.
    QueryIsActive,
    /// This query was not active.
    QueryNotActive,
    /// A query is active that is not included in the `inheritance` of the secondary command buffer.
    QueryNotInherited,
    /// Tried to use a graphics pipeline or secondary command buffer whose subpass index
    /// didn't match the current subpass index.
    WrongSubpassIndex,
    /// Tried to execute a secondary command buffer inside a subpass that only allows inline
    /// commands, or a draw command in a subpass that only allows secondary command buffers.
    WrongSubpassType,
}

impl error::Error for AutoCommandBufferBuilderContextError {}

impl fmt::Display for AutoCommandBufferBuilderContextError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            fmt,
            "{}",
            match *self {
                AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass => {
                    "operation forbidden inside of a render pass"
                }
                AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass => {
                    "operation forbidden outside of a render pass"
                }
                AutoCommandBufferBuilderContextError::IncompatibleFramebuffer => {
                    "tried to use a secondary command buffer with a specified framebuffer that is \
                 incompatible with the current framebuffer"
                }
                AutoCommandBufferBuilderContextError::IncompatibleRenderPass => {
                    "tried to use a graphics pipeline or secondary command buffer whose render pass \
                  is incompatible with the current render pass"
                }
                AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily => {
                    "the queue family doesn't allow this operation"
                }
                AutoCommandBufferBuilderContextError::NumSubpassesMismatch { .. } => {
                    "tried to end a render pass with subpasses remaining, or tried to go to next \
                 subpass with no subpass remaining"
                }
                AutoCommandBufferBuilderContextError::QueryIsActive => {
                    "a query is active that conflicts with the current operation"
                }
                AutoCommandBufferBuilderContextError::QueryNotActive => {
                    "this query was not active"
                }
                AutoCommandBufferBuilderContextError::QueryNotInherited => {
                    "a query is active that is not included in the inheritance of the secondary command buffer"
                }
                AutoCommandBufferBuilderContextError::WrongSubpassIndex => {
                    "tried to use a graphics pipeline whose subpass index didn't match the current \
                 subpass index"
                }
                AutoCommandBufferBuilderContextError::WrongSubpassType => {
                    "tried to execute a secondary command buffer inside a subpass that only allows \
                 inline commands, or a draw command in a subpass that only allows secondary \
                 command buffers"
                }
            }
        )
    }
}

#[cfg(test)]
mod tests {
    use crate::buffer::BufferUsage;
    use crate::buffer::CpuAccessibleBuffer;
    use crate::command_buffer::synced::SyncCommandBufferBuilderError;
    use crate::command_buffer::AutoCommandBufferBuilder;
    use crate::command_buffer::CommandBufferExecError;
    use crate::command_buffer::CommandBufferUsage;
    use crate::command_buffer::ExecuteCommandsError;
    use crate::command_buffer::PrimaryCommandBuffer;
    use crate::device::physical::PhysicalDevice;
    use crate::device::Device;
    use crate::device::DeviceExtensions;
    use crate::device::Features;
    use crate::sync::GpuFuture;
    use std::sync::Arc;

    #[test]
    fn copy_buffer_dimensions() {
        let instance = instance!();

        let phys = match PhysicalDevice::enumerate(&instance).next() {
            Some(p) => p,
            None => return,
        };

        let queue_family = match phys.queue_families().next() {
            Some(q) => q,
            None => return,
        };

        let (device, mut queues) = Device::new(
            phys,
            &Features::none(),
            &DeviceExtensions::none(),
            std::iter::once((queue_family, 0.5)),
        )
        .unwrap();

        let queue = queues.next().unwrap();

        let source = CpuAccessibleBuffer::from_iter(
            device.clone(),
            BufferUsage::all(),
            true,
            [1_u32, 2].iter().copied(),
        )
        .unwrap();

        let destination = CpuAccessibleBuffer::from_iter(
            device.clone(),
            BufferUsage::all(),
            true,
            [0_u32, 10, 20, 3, 4].iter().copied(),
        )
        .unwrap();

        let mut cbb = AutoCommandBufferBuilder::primary(
            device.clone(),
            queue.family(),
            CommandBufferUsage::OneTimeSubmit,
        )
        .unwrap();

        cbb.copy_buffer_dimensions(source.clone(), 0, destination.clone(), 1, 2)
            .unwrap();

        let cb = cbb.build().unwrap();

        let future = cb
            .execute(queue.clone())
            .unwrap()
            .then_signal_fence_and_flush()
            .unwrap();
        future.wait(None).unwrap();

        let result = destination.read().unwrap();

        assert_eq!(*result, [0_u32, 1, 2, 3, 4]);
    }

    #[test]
    fn secondary_nonconcurrent_conflict() {
        let (device, queue) = gfx_dev_and_queue!();

        // Make a secondary CB that doesn't support simultaneous use.
        let builder = AutoCommandBufferBuilder::secondary_compute(
            device.clone(),
            queue.family(),
            CommandBufferUsage::MultipleSubmit,
        )
        .unwrap();
        let secondary = Arc::new(builder.build().unwrap());

        {
            let mut builder = AutoCommandBufferBuilder::primary(
                device.clone(),
                queue.family(),
                CommandBufferUsage::SimultaneousUse,
            )
            .unwrap();

            // Add the secondary a first time
            builder.execute_commands(secondary.clone()).unwrap();

            // Recording the same non-concurrent secondary command buffer twice into the same
            // primary is an error.
            assert!(matches!(
                builder.execute_commands(secondary.clone()),
                Err(ExecuteCommandsError::SyncCommandBufferBuilderError(
                    SyncCommandBufferBuilderError::ExecError(
                        CommandBufferExecError::ExclusiveAlreadyInUse
                    )
                ))
            ));
        }

        {
            let mut builder = AutoCommandBufferBuilder::primary(
                device.clone(),
                queue.family(),
                CommandBufferUsage::SimultaneousUse,
            )
            .unwrap();
            builder.execute_commands(secondary.clone()).unwrap();
            let cb1 = builder.build().unwrap();

            let mut builder = AutoCommandBufferBuilder::primary(
                device.clone(),
                queue.family(),
                CommandBufferUsage::SimultaneousUse,
            )
            .unwrap();

            // Recording the same non-concurrent secondary command buffer into multiple
            // primaries is an error.
            assert!(matches!(
                builder.execute_commands(secondary.clone()),
                Err(ExecuteCommandsError::SyncCommandBufferBuilderError(
                    SyncCommandBufferBuilderError::ExecError(
                        CommandBufferExecError::ExclusiveAlreadyInUse
                    )
                ))
            ));

            std::mem::drop(cb1);

            // Now that the first cb is dropped, we should be able to record.
            builder.execute_commands(secondary.clone()).unwrap();
        }
    }
}
