use super::{
sys::Image, ImageAspects, ImageDescriptorLayouts, ImageDimensions, ImageLayout,
ImageSubresourceLayers, ImageSubresourceRange, ImageUsage, SampleCount,
};
use crate::{
device::{Device, DeviceOwned},
format::{Format, FormatFeatures},
SafeDeref,
};
use std::{
fmt::{Debug, Error as FmtError, Formatter},
hash::{Hash, Hasher},
sync::Arc,
};
pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
fn inner(&self) -> ImageInner<'_>;
#[inline]
fn dimensions(&self) -> ImageDimensions {
let inner = self.inner();
match self
.inner()
.image
.dimensions()
.mip_level_dimensions(inner.first_mipmap_level)
.unwrap()
{
ImageDimensions::Dim1d {
width,
array_layers: _,
} => ImageDimensions::Dim1d {
width,
array_layers: inner.num_layers,
},
ImageDimensions::Dim2d {
width,
height,
array_layers: _,
} => ImageDimensions::Dim2d {
width,
height,
array_layers: inner.num_layers,
},
ImageDimensions::Dim3d {
width,
height,
depth,
} => ImageDimensions::Dim3d {
width,
height,
depth,
},
}
}
#[inline]
fn format(&self) -> Format {
self.inner().image.format().unwrap()
}
#[inline]
fn format_features(&self) -> &FormatFeatures {
self.inner().image.format_features()
}
#[inline]
fn mip_levels(&self) -> u32 {
self.inner().num_mipmap_levels
}
#[inline]
fn samples(&self) -> SampleCount {
self.inner().image.samples()
}
#[inline]
fn usage(&self) -> &ImageUsage {
self.inner().image.usage()
}
#[inline]
fn stencil_usage(&self) -> &ImageUsage {
self.inner().image.stencil_usage()
}
#[inline]
fn subresource_layers(&self) -> ImageSubresourceLayers {
ImageSubresourceLayers::from_parameters(self.format(), self.dimensions().array_layers())
}
#[inline]
fn subresource_range(&self) -> ImageSubresourceRange {
ImageSubresourceRange {
aspects: ImageAspects {
plane0: false,
plane1: false,
plane2: false,
..self.format().aspects()
},
mip_levels: 0..self.mip_levels(),
array_layers: 0..self.dimensions().array_layers(),
}
}
#[inline]
unsafe fn layout_initialized(&self) {}
#[inline]
fn is_layout_initialized(&self) -> bool {
false
}
#[inline]
fn initial_layout(&self) -> ImageLayout {
self.inner().image.initial_layout()
}
fn initial_layout_requirement(&self) -> ImageLayout;
fn final_layout_requirement(&self) -> ImageLayout;
#[inline]
unsafe fn forced_undefined_initial_layout(
self,
preinitialized: bool,
) -> Arc<ImageAccessFromUndefinedLayout<Self>>
where
Self: Sized,
{
Arc::new(ImageAccessFromUndefinedLayout {
image: self,
preinitialized,
})
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ImageInner<'a> {
pub image: &'a Arc<Image>,
pub first_layer: u32,
pub num_layers: u32,
pub first_mipmap_level: u32,
pub num_mipmap_levels: u32,
}
impl Debug for dyn ImageAccess {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
f.debug_struct("dyn ImageAccess")
.field("inner", &self.inner())
.finish()
}
}
impl PartialEq for dyn ImageAccess {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl Eq for dyn ImageAccess {}
impl Hash for dyn ImageAccess {
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}
#[derive(Debug, Copy, Clone)]
pub struct ImageAccessFromUndefinedLayout<I> {
image: I,
preinitialized: bool,
}
unsafe impl<I> DeviceOwned for ImageAccessFromUndefinedLayout<I>
where
I: ImageAccess,
{
fn device(&self) -> &Arc<Device> {
self.image.device()
}
}
unsafe impl<I> ImageAccess for ImageAccessFromUndefinedLayout<I>
where
I: ImageAccess,
{
fn inner(&self) -> ImageInner<'_> {
self.image.inner()
}
fn initial_layout_requirement(&self) -> ImageLayout {
if self.preinitialized {
ImageLayout::Preinitialized
} else {
ImageLayout::Undefined
}
}
fn final_layout_requirement(&self) -> ImageLayout {
self.image.final_layout_requirement()
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
self.image.descriptor_layouts()
}
}
impl<I> PartialEq for ImageAccessFromUndefinedLayout<I>
where
I: ImageAccess,
{
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl<I> Eq for ImageAccessFromUndefinedLayout<I> where I: ImageAccess {}
impl<I> Hash for ImageAccessFromUndefinedLayout<I>
where
I: ImageAccess,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}
pub unsafe trait ImageContent<P>: ImageAccess {
fn matches_format(&self) -> bool;
}
unsafe impl<T> ImageAccess for T
where
T: SafeDeref + Send + Sync,
T::Target: ImageAccess,
{
fn inner(&self) -> ImageInner<'_> {
(**self).inner()
}
fn initial_layout_requirement(&self) -> ImageLayout {
(**self).initial_layout_requirement()
}
fn final_layout_requirement(&self) -> ImageLayout {
(**self).final_layout_requirement()
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
(**self).descriptor_layouts()
}
unsafe fn layout_initialized(&self) {
(**self).layout_initialized();
}
fn is_layout_initialized(&self) -> bool {
(**self).is_layout_initialized()
}
}