// Copyright (c) 2021 The Lutino Projects
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use nh_maths::Extent2D;

use crate::gpu_image::GpuImage;
use crate::image_view::create_image_view;
use crate::raw::*;
use crate::traits::{VulkanDeviceOwned, VulkanHandle};
use crate::vma::VmaMemoryUsageType;

pub struct SysGpuBuffer {
    inner: GpuImage,
    image_view: VkImageView,
}

impl SysGpuBuffer {
    pub fn new_depth(
        vd: &impl VulkanDeviceOwned,
        size: Extent2D,
        format: VulkanFormat,
        samples: SampleCount,
    ) -> SysGpuBuffer {
        let image = GpuImage::new(
            vd,
            ImageType::Image2D,
            size,
            format,
            samples,
            ImageUsage::TransientAttachment | ImageUsage::DepthStencilAttachment,
            VmaMemoryUsageType::GpuOnly,
        );

        let image_view = create_image_view(
            vd,
            image.object(),
            ImageAspect::Depth,
            format,
            ImageViewType::V2D,
            1,
        );

        SysGpuBuffer {
            inner: image,
            image_view,
        }
    }

    pub fn new_multisample(
        vd: &impl VulkanDeviceOwned,
        size: Extent2D,
        format: VulkanFormat,
        samples: SampleCount,
    ) -> SysGpuBuffer {
        let image = GpuImage::new(
            vd,
            ImageType::Image2D,
            size,
            format,
            samples,
            ImageUsage::TransientAttachment | ImageUsage::ColorAttachment,
            VmaMemoryUsageType::GpuOnly,
        );

        let image_view = create_image_view(
            vd,
            image.object(),
            ImageAspect::Color,
            format,
            ImageViewType::V2D,
            1,
        );

        SysGpuBuffer {
            inner: image,
            image_view,
        }
    }

    #[inline]
    pub const fn inner(&self) -> &GpuImage { &self.inner }

    #[inline]
    pub const fn image(&self) -> VkImage { self.inner().object() }

    #[inline]
    pub const fn image_view(&self) -> VkImageView { self.image_view }

    #[inline]
    pub const fn usage(&self) -> ImageUsage { self.inner.image_usage() }
}
