basalt 0.10.0

A window/ui framework built upon vulkan.
Documentation
use vulkano::image::{
    ImmutableImage, StorageImage, ImageLayout, ImageDescriptorLayouts, ImageInner,
    ImageViewAbstract, AttachmentImage, ImageAccess, ImageDimensions
};
use vulkano::image::view::{
    ImageViewType, UnsafeImageView, ImageView, ImageViewCreationError, ComponentMapping
};
use vulkano::image::immutable::SubImage;
use vulkano::sync::AccessError;
use vulkano::buffer::BufferAccess;
use vulkano::sampler::Sampler;
use vulkano::format::Format;
use std::sync::Arc;
use std::ops::Range;
use std::sync::atomic::{self, AtomicBool};

enum ImageVarient {
    Storage(Arc<StorageImage>),
    Immutable(Arc<ImmutableImage>),
    Sub(Arc<SubImage>),
    Attachment(Arc<AttachmentImage>),
}

unsafe impl ImageAccess for ImageVarient {
    #[inline]
    fn inner(&self) -> ImageInner<'_> {
        match self {
            Self::Storage(i) => i.inner(),
            Self::Immutable(i) => i.inner(),
            Self::Sub(i) => i.inner(),
            Self::Attachment(i) => i.inner(),
        }
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
        match self {
            Self::Storage(i) => i.initial_layout_requirement(),
            Self::Immutable(i) => i.initial_layout_requirement(),
            Self::Sub(i) => i.initial_layout_requirement(),
            Self::Attachment(i) => i.initial_layout_requirement(),
        }
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        match self {
            Self::Storage(i) => i.final_layout_requirement(),
            Self::Immutable(i) => i.final_layout_requirement(),
            Self::Sub(i) => i.final_layout_requirement(),
            Self::Attachment(i) => i.final_layout_requirement(),
        }
    }

    #[inline]
    fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
        match self {
            Self::Storage(i) => i.descriptor_layouts(),
            Self::Immutable(i) => i.descriptor_layouts(),
            Self::Sub(i) => i.descriptor_layouts(),
            Self::Attachment(i) => i.descriptor_layouts(),
        }
    }

    #[inline]
    fn conflicts_buffer(&self, other: &dyn BufferAccess) -> bool {
        match self {
            Self::Storage(i) => i.conflicts_buffer(other),
            Self::Immutable(i) => i.conflicts_buffer(other),
            Self::Sub(i) => i.conflicts_buffer(other),
            Self::Attachment(i) => i.conflicts_buffer(other),
        }
    }

    #[inline]
    fn conflicts_image(&self, other: &dyn ImageAccess) -> bool {
        match self {
            Self::Storage(i) => i.conflicts_image(other),
            Self::Immutable(i) => i.conflicts_image(other),
            Self::Sub(i) => i.conflicts_image(other),
            Self::Attachment(i) => i.conflicts_image(other),
        }
    }

    #[inline]
    fn conflict_key(&self) -> u64 {
        match self {
            Self::Storage(i) => i.conflict_key(),
            Self::Immutable(i) => i.conflict_key(),
            Self::Sub(i) => i.conflict_key(),
            Self::Attachment(i) => i.conflict_key(),
        }
    }

    #[inline]
    fn current_miplevels_access(&self) -> Range<u32> {
        match self {
            Self::Storage(i) => i.current_miplevels_access(),
            Self::Immutable(i) => i.current_miplevels_access(),
            Self::Sub(i) => i.current_miplevels_access(),
            Self::Attachment(i) => i.current_miplevels_access(),
        }
    }

    #[inline]
    fn current_layer_levels_access(&self) -> Range<u32> {
        match self {
            Self::Storage(i) => i.current_layer_levels_access(),
            Self::Immutable(i) => i.current_layer_levels_access(),
            Self::Sub(i) => i.current_layer_levels_access(),
            Self::Attachment(i) => i.current_layer_levels_access(),
        }
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, expected_layout: ImageLayout) -> Result<(), AccessError> {
        match self {
            Self::Storage(i) => i.try_gpu_lock(exclusive_access, expected_layout),
            Self::Immutable(i) => i.try_gpu_lock(exclusive_access, expected_layout),
            Self::Sub(i) => i.try_gpu_lock(exclusive_access, expected_layout),
            Self::Attachment(i) => i.try_gpu_lock(exclusive_access, expected_layout),
        }
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        match self {
            Self::Storage(i) => i.increase_gpu_lock(),
            Self::Immutable(i) => i.increase_gpu_lock(),
            Self::Sub(i) => i.increase_gpu_lock(),
            Self::Attachment(i) => i.increase_gpu_lock(),
        }
    }

    #[inline]
    unsafe fn unlock(&self, transitioned_layout: Option<ImageLayout>) {
        match self {
            Self::Storage(i) => i.unlock(transitioned_layout),
            Self::Immutable(i) => i.unlock(transitioned_layout),
            Self::Sub(i) => i.unlock(transitioned_layout),
            Self::Attachment(i) => i.unlock(transitioned_layout),
        }
    }
}

enum ViewVarient {
    Parent(Arc<ImageView<ImageVarient>>),
    Child(Arc<BstImageView>, Arc<AtomicBool>),
}

pub struct BstImageView {
    view: ViewVarient,
}

impl BstImageView {
    pub fn from_storage(image: Arc<StorageImage>) -> Result<Arc<Self>, ImageViewCreationError> {
        Ok(Arc::new(BstImageView {
            view: ViewVarient::Parent(ImageView::new(ImageVarient::Storage(image))?)
        }))
    }

    pub fn from_immutable(image: Arc<ImmutableImage>) -> Result<Arc<Self>, ImageViewCreationError> {
        Ok(Arc::new(BstImageView {
            view: ViewVarient::Parent(ImageView::new(ImageVarient::Immutable(image))?)
        }))
    }

    pub fn from_sub(image: Arc<SubImage>) -> Result<Arc<Self>, ImageViewCreationError> {
        Ok(Arc::new(BstImageView {
            view: ViewVarient::Parent(ImageView::new(ImageVarient::Sub(image))?)
        }))
    }

    pub fn from_attachment(image: Arc<AttachmentImage>) -> Result<Arc<Self>, ImageViewCreationError> {
        Ok(Arc::new(BstImageView {
            view: ViewVarient::Parent(ImageView::new(ImageVarient::Attachment(image))?)
        }))
    }

    pub fn create_tmp(self: &Arc<Self>) -> (Arc<Self>, Arc<AtomicBool>) {
        let alive_ret = Arc::new(AtomicBool::new(true));

        (
            Arc::new(Self {
                view: ViewVarient::Child(self.clone(), alive_ret.clone())
            }),
            alive_ret
        )
    }

    #[inline]
    fn image_view(&self) -> Arc<ImageView<ImageVarient>> {
        match &self.view {
            ViewVarient::Parent(i) => i.clone(),
            ViewVarient::Child(p, _) => p.image_view()
        }
    }

    #[inline]
    fn image_view_ref(&self) -> &Arc<ImageView<ImageVarient>> {
        match &self.view {
            ViewVarient::Parent(ref i) => i,
            ViewVarient::Child(p, _) => p.image_view_ref()
        }
    }

    #[inline]
    pub fn dimensions(&self) -> ImageDimensions {
        self.image_view().image().dimensions()
    }
}

unsafe impl ImageViewAbstract for BstImageView {
    #[inline]
    fn image(&self) -> &dyn ImageAccess {
        self.image_view_ref().image()
    }

    #[inline]
    fn inner(&self) -> &UnsafeImageView {
        self.image_view_ref().inner()
    }
    
    #[inline]
    fn array_layers(&self) -> Range<u32> {
        self.image_view_ref().array_layers()
    }
    
    #[inline]
    fn format(&self) -> Format {
        self.image_view_ref().format()
    }
    
    #[inline]
    fn component_mapping(&self) -> ComponentMapping {
        self.image_view_ref().component_mapping()
    }
    
    #[inline]
    fn ty(&self) -> ImageViewType {
        self.image_view_ref().ty()
    }

    #[inline]
    fn can_be_sampled(&self, _sampler: &Sampler) -> bool {
        self.image_view_ref().can_be_sampled(_sampler)
    }
}

unsafe impl ImageAccess for BstImageView {
    #[inline]
    fn inner(&self) -> ImageInner<'_> {
        self.image_view_ref().image().inner()
    }

    #[inline]
    fn initial_layout_requirement(&self) -> ImageLayout {
       self.image_view_ref().image().initial_layout_requirement()
    }

    #[inline]
    fn final_layout_requirement(&self) -> ImageLayout {
        self.image_view_ref().image().final_layout_requirement()
    }

    #[inline]
    fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
        self.image_view_ref().image().descriptor_layouts()
    }

    #[inline]
    fn conflicts_buffer(&self, other: &dyn BufferAccess) -> bool {
        self.image_view_ref().image().conflicts_buffer(other)
    }

    #[inline]
    fn conflicts_image(&self, other: &dyn ImageAccess) -> bool {
        self.image_view_ref().image().conflicts_image(other)
    }

    #[inline]
    fn conflict_key(&self) -> u64 {
        self.image_view_ref().image().conflict_key()
    }

    #[inline]
    fn current_miplevels_access(&self) -> Range<u32> {
        self.image_view_ref().image().current_miplevels_access()
    }

    #[inline]
    fn current_layer_levels_access(&self) -> Range<u32> {
        self.image_view_ref().image().current_layer_levels_access()
    }

    #[inline]
    fn try_gpu_lock(&self, exclusive_access: bool, expected_layout: ImageLayout) -> Result<(), AccessError> {
        self.image_view_ref().image().try_gpu_lock(exclusive_access, expected_layout)
    }

    #[inline]
    unsafe fn increase_gpu_lock(&self) {
        self.image_view_ref().image().increase_gpu_lock()
    }

    #[inline]
    unsafe fn unlock(&self, transitioned_layout: Option<ImageLayout>) {
        self.image_view_ref().image().unlock(transitioned_layout)
    }
}

impl Drop for BstImageView {
	fn drop(&mut self) {
        match &self.view {
            ViewVarient::Parent(_) => (),
            ViewVarient::Child(_, alive) => {
		        alive.store(false, atomic::Ordering::SeqCst);
            }
        }
    }
}