mev 0.1.0

Metal Et Vulkan abstraction
Documentation
use std::{fmt, hash, rc::Rc};

use crate::{
    generic::{ImageDesc, ImageExtent, ImageUsage, PixelFormat, ViewDesc},
    ArgumentKind, Automatic, Sampled, Storage,
};

use super::{
    arguments::ArgumentsField,
    from::{IntoWgpu, WgpuInto},
    Device,
};

pub(super) struct ImageInner {
    texture: Rc<wgpu::Texture>,
    view: wgpu::TextureView,
    format: PixelFormat,
    extent: ImageExtent,
    layers: u32,
    levels: u32,
    usage: ImageUsage,
}

#[derive(Clone)]
pub struct Image {
    view: wgpu::TextureView,
    base_layer: u32,
    layers: u32,
    base_level: u32,
    levels: u32,
}

impl Image {
    pub(super) fn new(view: wgpu::TextureView, layers: u32, levels: u32) -> Self {
        Image {
            view,
            base_layer: 0,
            layers,
            base_level: 0,
            levels,
        }
    }

    pub(super) fn wgpu_view(&self) -> &wgpu::TextureView {
        &self.view
    }

    pub(super) fn base_layer(&self) -> u32 {
        self.base_layer
    }

    pub(super) fn base_level(&self) -> u32 {
        self.base_level
    }
}

impl fmt::Debug for Image {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Image").field("view", &self.view).finish()
    }
}

impl PartialEq for Image {
    fn eq(&self, other: &Self) -> bool {
        self.view == other.view
    }
}

impl Eq for Image {}

impl hash::Hash for Image {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.view.hash(state);
    }
}

impl crate::traits::Resource for Image {}

#[hidden_trait::expose]
impl crate::traits::Image for Image {
    fn format(&self) -> PixelFormat {
        self.view.texture().format().wgpu_into()
    }

    fn extent(&self) -> ImageExtent {
        (self.view.texture().dimension(), self.view.texture().size()).wgpu_into()
    }

    fn layers(&self) -> u32 {
        self.layers
    }

    fn levels(&self) -> u32 {
        self.levels
    }

    fn usage(&self) -> ImageUsage {
        self.view.texture().usage().wgpu_into()
    }

    fn view(&self, device: &Device, desc: ViewDesc) -> Image {
        let view_desc = wgpu::TextureViewDescriptor {
            label: None,
            format: Some(desc.format.into_wgpu()),
            dimension: None,
            usage: None,
            aspect: wgpu::TextureAspect::All,
            base_mip_level: desc.base_level + self.base_level,
            mip_level_count: Some(desc.levels),
            base_array_layer: desc.base_layer + self.base_layer,
            array_layer_count: Some(desc.layers),
        };

        let view = self.view.texture().create_view(&view_desc);

        Image {
            view,
            base_layer: desc.base_layer + self.base_layer,
            layers: desc.layers,
            base_level: desc.base_level + self.base_level,
            levels: desc.levels,
        }
    }

    fn detached(&self) -> bool {
        false
    }
}

impl ArgumentsField<Automatic> for Image {
    const KIND: ArgumentKind = crate::generic::ArgumentKind::SampledImage;
    const SIZE: usize = 1;

    fn as_binding_resource(&self) -> wgpu::BindingResource<'_> {
        wgpu::BindingResource::TextureView(self.wgpu_view())
    }
}

impl ArgumentsField<Sampled> for Image {
    const KIND: ArgumentKind = crate::generic::ArgumentKind::SampledImage;
    const SIZE: usize = 1;

    fn as_binding_resource(&self) -> wgpu::BindingResource<'_> {
        wgpu::BindingResource::TextureView(self.wgpu_view())
    }
}

impl ArgumentsField<Storage> for Image {
    const KIND: ArgumentKind = crate::generic::ArgumentKind::StorageImage;
    const SIZE: usize = 1;

    fn as_binding_resource(&self) -> wgpu::BindingResource<'_> {
        wgpu::BindingResource::TextureView(self.wgpu_view())
    }
}