pub use {
self::Samples::*,
crate::{access::AccessFlags, backend::Image},
};
use {
crate::{
format::{AspectFlags, Format},
Extent2d, Extent3d, ImageSize, Offset3d,
},
std::ops::Range,
};
bitflags::bitflags! {
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageUsage: u32 {
const TRANSFER_SRC = 0x001;
const TRANSFER_DST = 0x002;
const SAMPLED = 0x004;
const STORAGE = 0x008;
const COLOR_ATTACHMENT = 0x010;
const DEPTH_STENCIL_ATTACHMENT = 0x020;
const TRANSIENT_ATTACHMENT = 0x040;
const INPUT_ATTACHMENT = 0x080;
const TRANSIENT = 0x100;
}
}
impl ImageUsage {
pub fn is_render_target(self) -> bool {
self.intersects(Self::COLOR_ATTACHMENT | Self::DEPTH_STENCIL_ATTACHMENT)
}
pub fn is_render_target_only(self) -> bool {
self.is_render_target()
&& !self.intersects(
Self::TRANSFER_SRC
| Self::TRANSFER_DST
| Self::SAMPLED
| Self::STORAGE
| Self::INPUT_ATTACHMENT,
)
}
pub fn is_read_only(self) -> bool {
!self.intersects(
Self::TRANSFER_DST
| Self::STORAGE
| Self::COLOR_ATTACHMENT
| Self::DEPTH_STENCIL_ATTACHMENT,
)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub enum Layout {
General,
ColorAttachmentOptimal,
DepthStencilAttachmentOptimal,
DepthStencilReadOnlyOptimal,
ShaderReadOnlyOptimal,
TransferSrcOptimal,
TransferDstOptimal,
Present,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub enum ImageExtent {
D1 {
width: ImageSize,
},
D2 {
width: ImageSize,
height: ImageSize,
},
D3 {
width: ImageSize,
height: ImageSize,
depth: ImageSize,
},
}
impl From<Extent2d> for ImageExtent {
fn from(extent: Extent2d) -> Self {
ImageExtent::D2 {
width: extent.width,
height: extent.height,
}
}
}
impl From<Extent3d> for ImageExtent {
fn from(extent: Extent3d) -> Self {
ImageExtent::D3 {
width: extent.width,
height: extent.height,
depth: extent.depth,
}
}
}
impl ImageExtent {
pub fn into_3d(self) -> Extent3d {
match self {
Self::D1 { width } => Extent3d {
width,
height: 1,
depth: 1,
},
Self::D2 { width, height } => Extent3d {
width,
height,
depth: 1,
},
Self::D3 {
width,
height,
depth,
} => Extent3d {
width,
height,
depth,
},
}
}
pub fn into_2d(self) -> Extent2d {
match self {
Self::D1 { width } => Extent2d { width, height: 1 },
Self::D2 { width, height } => Extent2d { width, height },
Self::D3 { width, height, .. } => Extent2d { width, height },
}
}
}
impl PartialEq<Extent2d> for ImageExtent {
fn eq(&self, rhs: &Extent2d) -> bool {
match self {
ImageExtent::D2 { width, height } => *width == rhs.width && *height == rhs.height,
_ => false,
}
}
}
impl PartialEq<Extent3d> for ImageExtent {
fn eq(&self, rhs: &Extent3d) -> bool {
match self {
ImageExtent::D3 {
width,
height,
depth,
} => *width == rhs.width && *height == rhs.height && *depth == rhs.depth,
_ => false,
}
}
}
impl PartialEq<ImageExtent> for Extent2d {
fn eq(&self, rhs: &ImageExtent) -> bool {
match rhs {
ImageExtent::D2 { width, height } => self.width == *width && self.height == *height,
_ => false,
}
}
}
impl PartialEq<ImageExtent> for Extent3d {
fn eq(&self, rhs: &ImageExtent) -> bool {
match rhs {
ImageExtent::D3 {
width,
height,
depth,
} => self.width == *width && self.height == *height && self.depth == *depth,
_ => false,
}
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub enum Samples {
Samples1,
Samples2,
Samples4,
Samples8,
Samples16,
Samples32,
Samples64,
}
impl Default for Samples {
fn default() -> Self {
Samples::Samples1
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageInfo {
pub extent: ImageExtent,
pub format: Format,
pub levels: u32,
pub layers: u32,
pub samples: Samples,
pub usage: ImageUsage,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageSubresourceRange {
pub aspect: AspectFlags,
pub first_level: u32,
pub level_count: u32,
pub first_layer: u32,
pub layer_count: u32,
}
impl ImageSubresourceRange {
pub fn new(aspect: AspectFlags, levels: Range<u32>, layers: Range<u32>) -> Self {
assert!(levels.end >= levels.start);
assert!(layers.end >= layers.start);
ImageSubresourceRange {
aspect,
first_level: levels.start,
level_count: levels.end - levels.start,
first_layer: layers.start,
layer_count: layers.end - layers.start,
}
}
pub fn whole(info: &ImageInfo) -> Self {
ImageSubresourceRange {
aspect: info.format.aspect_flags(),
first_level: 0,
level_count: info.levels,
first_layer: 0,
layer_count: info.layers,
}
}
pub fn color(levels: Range<u32>, layers: Range<u32>) -> Self {
Self::new(AspectFlags::COLOR, levels, layers)
}
pub fn depth(levels: Range<u32>, layers: Range<u32>) -> Self {
Self::new(AspectFlags::DEPTH, levels, layers)
}
pub fn stencil(levels: Range<u32>, layers: Range<u32>) -> Self {
Self::new(AspectFlags::STENCIL, levels, layers)
}
pub fn depth_stencil(levels: Range<u32>, layers: Range<u32>) -> Self {
Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, levels, layers)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageSubresourceLayers {
pub aspect: AspectFlags,
pub level: u32,
pub first_layer: u32,
pub layer_count: u32,
}
impl ImageSubresourceLayers {
pub fn new(aspect: AspectFlags, level: u32, layers: Range<u32>) -> Self {
assert!(layers.end >= layers.start);
ImageSubresourceLayers {
aspect,
level,
first_layer: layers.start,
layer_count: layers.end - layers.start,
}
}
pub fn all_layers(info: &ImageInfo, level: u32) -> Self {
assert!(level < info.levels);
ImageSubresourceLayers {
aspect: info.format.aspect_flags(),
level,
first_layer: 0,
layer_count: info.layers,
}
}
pub fn color(level: u32, layers: Range<u32>) -> Self {
Self::new(AspectFlags::COLOR, level, layers)
}
pub fn depth(level: u32, layers: Range<u32>) -> Self {
Self::new(AspectFlags::DEPTH, level, layers)
}
pub fn stencil(level: u32, layers: Range<u32>) -> Self {
Self::new(AspectFlags::STENCIL, level, layers)
}
pub fn depth_stencil(level: u32, layers: Range<u32>) -> Self {
Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, level, layers)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageSubresource {
pub aspect: AspectFlags,
pub level: u32,
pub layer: u32,
}
impl ImageSubresource {
pub fn new(aspect: AspectFlags, level: u32, layer: u32) -> Self {
ImageSubresource {
aspect,
level,
layer,
}
}
pub fn from_info(info: &ImageInfo, level: u32, layer: u32) -> Self {
assert!(level < info.levels);
assert!(layer < info.layers);
ImageSubresource {
aspect: info.format.aspect_flags(),
level,
layer,
}
}
pub fn color(level: u32, layer: u32) -> Self {
Self::new(AspectFlags::COLOR, level, layer)
}
pub fn depth(level: u32, layer: u32) -> Self {
Self::new(AspectFlags::DEPTH, level, layer)
}
pub fn stencil(level: u32, layer: u32) -> Self {
Self::new(AspectFlags::STENCIL, level, layer)
}
pub fn depth_stencil(level: u32, layer: u32) -> Self {
Self::new(AspectFlags::DEPTH | AspectFlags::STENCIL, level, layer)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageBlit {
pub src_subresource: ImageSubresourceLayers,
pub src_offsets: [Offset3d; 2],
pub dst_subresource: ImageSubresourceLayers,
pub dst_offsets: [Offset3d; 2],
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct ImageLayoutTransition<'a> {
pub image: &'a Image,
pub old: Option<(AccessFlags, Layout)>,
pub new: (AccessFlags, Layout),
pub subresource: ImageSubresourceRange,
}
impl<'a> ImageLayoutTransition<'a> {
pub fn transition_whole(image: &'a Image, range: Range<(AccessFlags, Layout)>) -> Self {
ImageLayoutTransition {
subresource: ImageSubresourceRange::whole(image.info()),
image,
old: Some(range.start),
new: range.end,
}
}
pub fn initialize_whole(image: &'a Image, access: AccessFlags, layout: Layout) -> Self {
ImageLayoutTransition {
subresource: ImageSubresourceRange::whole(image.info()),
image,
old: None,
new: (access, layout),
}
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct ImageMemoryBarrier<'a> {
pub image: &'a Image,
pub old: Option<(AccessFlags, Layout)>,
pub new: (AccessFlags, Layout),
pub family_transfer: Option<Range<u32>>,
pub subresource: ImageSubresourceRange,
}
impl<'a> From<ImageLayoutTransition<'a>> for ImageMemoryBarrier<'a> {
fn from(value: ImageLayoutTransition<'a>) -> Self {
ImageMemoryBarrier {
image: value.image,
old: value.old,
new: value.new,
family_transfer: None,
subresource: value.subresource,
}
}
}