use crate::sealed::Sealed;
pub use {
self::Samples::*,
crate::{
access::Access,
backend::Image,
encode::Encoder,
queue::{Ownership, QueueId},
stage::PipelineStages,
},
};
use {
crate::{
format::{AspectFlags, Format},
Extent2, Extent3, ImageSize, Offset3,
},
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 INPUT_ATTACHMENT = 0x080;
}
}
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,
}
impl Default for Layout {
fn default() -> Self {
Self::General
}
}
#[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<Extent2> for ImageExtent {
fn from(extent: Extent2) -> Self {
ImageExtent::D2 {
width: extent.width,
height: extent.height,
}
}
}
impl From<Extent3> for ImageExtent {
fn from(extent: Extent3) -> Self {
ImageExtent::D3 {
width: extent.width,
height: extent.height,
depth: extent.depth,
}
}
}
impl ImageExtent {
pub fn into_3d(self) -> Extent3 {
match self {
Self::D1 { width } => Extent3::new(width, 1, 1),
Self::D2 { width, height } => Extent3::new(width, height, 1),
Self::D3 {
width,
height,
depth,
} => Extent3::new(width, height, depth),
}
}
pub fn into_2d(self) -> Extent2 {
match self {
Self::D1 { width } => Extent2::new(width, 1),
Self::D2 { width, height } => Extent2::new(width, height),
Self::D3 { width, height, .. } => Extent2::new(width, height),
}
}
}
impl PartialEq<Extent2> for ImageExtent {
fn eq(&self, rhs: &Extent2) -> bool {
match self {
ImageExtent::D2 { width, height } => *width == rhs.width && *height == rhs.height,
_ => false,
}
}
}
impl PartialEq<Extent3> for ImageExtent {
fn eq(&self, rhs: &Extent3) -> bool {
match self {
ImageExtent::D3 {
width,
height,
depth,
} => *width == rhs.width && *height == rhs.height && *depth == rhs.depth,
_ => false,
}
}
}
impl PartialEq<ImageExtent> for Extent2 {
fn eq(&self, rhs: &ImageExtent) -> bool {
match rhs {
ImageExtent::D2 { width, height } => self.width == *width && self.height == *height,
_ => false,
}
}
}
impl PartialEq<ImageExtent> for Extent3 {
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 SubresourceRange {
pub aspect: AspectFlags,
pub first_level: u32,
pub level_count: u32,
pub first_layer: u32,
pub layer_count: u32,
}
impl SubresourceRange {
pub fn new(aspect: AspectFlags, levels: Range<u32>, layers: Range<u32>) -> Self {
assert!(levels.end >= levels.start);
assert!(layers.end >= layers.start);
SubresourceRange {
aspect,
first_level: levels.start,
level_count: levels.end - levels.start,
first_layer: layers.start,
layer_count: layers.end - layers.start,
}
}
pub fn subresource(subresource: Subresource) -> Self {
SubresourceRange {
aspect: subresource.aspect,
first_level: subresource.level,
level_count: 1,
first_layer: subresource.layer,
layer_count: 1,
}
}
pub fn layers(layers: SubresourceLayers) -> Self {
SubresourceRange {
aspect: layers.aspect,
first_level: layers.level,
level_count: 1,
first_layer: layers.first_layer,
layer_count: layers.layer_count,
}
}
pub fn whole(info: &ImageInfo) -> Self {
SubresourceRange {
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 SubresourceLayers {
pub aspect: AspectFlags,
pub level: u32,
pub first_layer: u32,
pub layer_count: u32,
}
impl SubresourceLayers {
pub fn new(aspect: AspectFlags, level: u32, layers: Range<u32>) -> Self {
assert!(layers.end >= layers.start);
SubresourceLayers {
aspect,
level,
first_layer: layers.start,
layer_count: layers.end - layers.start,
}
}
pub fn subresource(subresource: Subresource) -> Self {
SubresourceLayers {
aspect: subresource.aspect,
level: subresource.level,
first_layer: subresource.layer,
layer_count: 1,
}
}
pub fn all_layers(info: &ImageInfo, level: u32) -> Self {
assert!(level < info.levels);
SubresourceLayers {
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)
}
}
impl From<SubresourceLayers> for SubresourceRange {
fn from(layers: SubresourceLayers) -> Self {
SubresourceRange::layers(layers)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct Subresource {
pub aspect: AspectFlags,
pub level: u32,
pub layer: u32,
}
impl Subresource {
pub fn new(aspect: AspectFlags, level: u32, layer: u32) -> Self {
Subresource {
aspect,
level,
layer,
}
}
pub fn from_info(info: &ImageInfo, level: u32, layer: u32) -> Self {
assert!(level < info.levels);
assert!(layer < info.layers);
Subresource {
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)
}
}
impl From<Subresource> for SubresourceLayers {
fn from(subresource: Subresource) -> Self {
SubresourceLayers::subresource(subresource)
}
}
impl From<Subresource> for SubresourceRange {
fn from(subresource: Subresource) -> Self {
SubresourceRange::subresource(subresource)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(serde::Serialize, serde::Deserialize))]
pub struct ImageBlit {
pub src_subresource: SubresourceLayers,
pub src_offsets: [Offset3; 2],
pub dst_subresource: SubresourceLayers,
pub dst_offsets: [Offset3; 2],
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub struct LayoutTransition<'a> {
pub image: &'a Image,
pub old_access: Access,
pub old_layout: Option<Layout>,
pub new_access: Access,
pub new_layout: Layout,
pub range: SubresourceRange,
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub struct ImageMemoryBarrier<'a> {
pub image: &'a Image,
pub old_access: Access,
pub old_layout: Option<Layout>,
pub new_access: Access,
pub new_layout: Layout,
pub family_transfer: Option<(u32, u32)>,
pub range: SubresourceRange,
}
impl<'a> ImageMemoryBarrier<'a> {
pub fn transition_whole(
image: &'a Image,
access: Range<Access>,
layout: Range<Layout>,
) -> Self {
ImageMemoryBarrier {
range: SubresourceRange::whole(image.info()),
image,
old_access: access.start,
new_access: access.end,
old_layout: Some(layout.start),
new_layout: layout.end,
family_transfer: None,
}
}
pub fn initialize_whole(image: &'a Image, access: Access, layout: Layout) -> Self {
ImageMemoryBarrier {
range: SubresourceRange::whole(image.info()),
image,
old_access: Access::empty(),
old_layout: None,
new_access: access,
new_layout: layout,
family_transfer: None,
}
}
}
impl<'a> From<LayoutTransition<'a>> for ImageMemoryBarrier<'a> {
fn from(value: LayoutTransition<'a>) -> Self {
ImageMemoryBarrier {
image: value.image,
old_access: value.old_access,
old_layout: value.old_layout,
new_access: value.new_access,
new_layout: value.new_layout,
family_transfer: None,
range: value.range,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ImageSubresourceRange {
pub image: Image,
pub range: SubresourceRange,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ImageSubresourceState {
pub subresource: ImageSubresourceRange,
pub access: Access,
pub stages: PipelineStages,
pub layout: Option<Layout>,
pub family: Ownership,
}
impl ImageSubresourceState {
pub fn access<'a>(
&'a mut self,
access: Access,
stages: PipelineStages,
layout: Layout,
queue: QueueId,
encoder: &mut Encoder<'a>,
) -> &'a Self {
match self.family {
Ownership::NotOwned => encoder.image_barriers(
self.stages,
stages,
encoder.scope().to_scope([ImageMemoryBarrier {
image: &self.subresource.image,
old_access: self.access,
new_access: access,
old_layout: self.layout,
new_layout: layout,
family_transfer: None,
range: self.subresource.range,
}]),
),
Ownership::Owned { family } => {
assert_eq!(family, queue.family, "Wrong queue family owns the buffer");
encoder.image_barriers(
self.stages,
stages,
encoder.scope().to_scope([ImageMemoryBarrier {
image: &self.subresource.image,
old_access: self.access,
new_access: access,
old_layout: self.layout,
new_layout: layout,
family_transfer: None,
range: self.subresource.range,
}]),
)
}
Ownership::Transition { from, to } => {
assert_eq!(
to, queue.family,
"Image is being transitioned to wrong queue family"
);
encoder.image_barriers(
self.stages,
stages,
encoder.scope().to_scope([ImageMemoryBarrier {
image: &self.subresource.image,
old_access: self.access,
new_access: access,
old_layout: self.layout,
new_layout: layout,
family_transfer: Some((from, to)),
range: self.subresource.range,
}]),
)
}
}
self.stages = stages;
self.access = access;
self.layout = Some(layout);
self
}
pub fn overwrite<'a>(
&'a mut self,
access: Access,
stages: PipelineStages,
layout: Layout,
queue: QueueId,
encoder: &mut Encoder<'a>,
) -> &'a ImageSubresourceRange {
encoder.image_barriers(
self.stages,
stages,
encoder.scope().to_scope([ImageMemoryBarrier {
image: &self.subresource.image,
old_access: Access::empty(),
new_access: access,
old_layout: None,
new_layout: layout,
family_transfer: None,
range: self.subresource.range,
}]),
);
self.family = Ownership::Owned {
family: queue.family,
};
self.stages = stages;
self.access = access;
self.layout = Some(layout);
&self.subresource
}
}
#[derive(Copy, Clone, Debug)]
pub enum ColorAttachmentOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum DepthStencilAttachmentOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum DepthStencilReadOnlyOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum ShaderReadOnlyOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum TransferSrcOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum TransferDstOptimal {}
#[derive(Copy, Clone, Debug)]
pub enum Present {}
#[derive(Copy, Clone, Debug)]
pub enum General {}
pub trait StaticLayout {
const LAYOUT: Layout;
}
impl StaticLayout for ColorAttachmentOptimal {
const LAYOUT: Layout = Layout::ColorAttachmentOptimal;
}
impl StaticLayout for DepthStencilAttachmentOptimal {
const LAYOUT: Layout = Layout::DepthStencilAttachmentOptimal;
}
impl StaticLayout for DepthStencilReadOnlyOptimal {
const LAYOUT: Layout = Layout::DepthStencilReadOnlyOptimal;
}
impl StaticLayout for ShaderReadOnlyOptimal {
const LAYOUT: Layout = Layout::ShaderReadOnlyOptimal;
}
impl StaticLayout for TransferSrcOptimal {
const LAYOUT: Layout = Layout::TransferSrcOptimal;
}
impl StaticLayout for TransferDstOptimal {
const LAYOUT: Layout = Layout::TransferDstOptimal;
}
impl StaticLayout for Present {
const LAYOUT: Layout = Layout::Present;
}
impl StaticLayout for General {
const LAYOUT: Layout = Layout::General;
}
impl Sealed for (Image, Layout) {}