use std::ops::Range;
use crate::buffer::Offset as RawOffset;
use crate::device;
use crate::format;
use crate::pso::{Comparison, Rect};
pub type Size = u32;
pub type NumSamples = u8;
pub type Layer = u16;
pub type Level = u8;
pub const MAX_LEVEL: Level = 15;
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Extent {
pub width: Size,
pub height: Size,
pub depth: Size,
}
impl Extent {
pub fn is_empty(&self) -> bool {
self.width == 0 || self.height == 0 || self.depth == 0
}
pub fn at_level(&self, level: Level) -> Self {
Extent {
width: 1.max(self.width >> level),
height: 1.max(self.height >> level),
depth: 1.max(self.depth >> level),
}
}
pub fn rect(&self) -> Rect {
Rect {
x: 0,
y: 0,
w: self.width as i16,
h: self.height as i16,
}
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Offset {
pub x: i32,
pub y: i32,
pub z: i32,
}
impl Offset {
pub const ZERO: Self = Offset { x: 0, y: 0, z: 0 };
pub fn into_bounds(self, extent: &Extent) -> Range<Offset> {
let end = Offset {
x: self.x + extent.width as i32,
y: self.y + extent.height as i32,
z: self.z + extent.depth as i32,
};
self..end
}
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Tiling {
Optimal,
Linear,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Fail)]
pub enum CreationError {
#[fail(display = "{}", _0)]
OutOfMemory(device::OutOfMemory),
#[fail(display = "Failed to map a given format ({:?}) to the device", _0)]
Format(format::Format),
#[fail(display = "The kind doesn't support a particular operation")]
Kind,
#[fail(
display = "Failed to map a given multisampled kind ({}) to the device",
_0
)]
Samples(NumSamples),
#[fail(display = "Unsupported size ({}) in one of the dimensions", _0)]
Size(Size),
#[fail(
display = "The given data has a different size ({}) than the target image slice",
_0
)]
Data(usize),
#[fail(
display = "The expected image usage mode ({:?}) is not supported by a graphic API",
_0
)]
Usage(Usage),
}
impl From<device::OutOfMemory> for CreationError {
fn from(error: device::OutOfMemory) -> Self {
CreationError::OutOfMemory(error)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Fail)]
pub enum ViewError {
#[fail(
display = "The required usage flag ({:?}) is not present in the image",
_0
)]
Usage(Usage),
#[fail(display = "Selected mip level ({}) doesn't exist", _0)]
Level(Level),
#[fail(display = "Selected mip layer ({}) doesn't exist", _0)]
Layer(LayerError),
#[fail(
display = "An incompatible format ({:?}) was requested for the view",
_0
)]
BadFormat(format::Format),
#[fail(display = "An incompatible kind ({:?}) was requested for the view", _0)]
BadKind(ViewKind),
#[fail(display = "{}", _0)]
OutOfMemory(device::OutOfMemory),
#[fail(display = "The backend refused for some reason")]
Unsupported,
}
impl From<device::OutOfMemory> for ViewError {
fn from(error: device::OutOfMemory) -> Self {
ViewError::OutOfMemory(error)
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq, Fail)]
pub enum LayerError {
#[fail(
display = "The source image kind ({:?}) doesn't support array slices",
_0
)]
NotExpected(Kind),
#[fail(
display = "Selected layers ({:?}) are outside of the provided range",
_0
)]
OutOfBounds(Range<Layer>),
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Filter {
Nearest,
Linear,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Anisotropic {
Off,
On(u8),
}
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum CubeFace {
PosX,
NegX,
PosY,
NegY,
PosZ,
NegZ,
}
pub const CUBE_FACES: [CubeFace; 6] = [
CubeFace::PosX,
CubeFace::NegX,
CubeFace::PosY,
CubeFace::NegY,
CubeFace::PosZ,
CubeFace::NegZ,
];
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Kind {
D1(Size, Layer),
D2(Size, Size, Layer, NumSamples),
D3(Size, Size, Size),
}
impl Kind {
pub fn extent(&self) -> Extent {
match *self {
Kind::D1(width, _) => Extent {
width,
height: 1,
depth: 1,
},
Kind::D2(width, height, _, _) => Extent {
width,
height,
depth: 1,
},
Kind::D3(width, height, depth) => Extent {
width,
height,
depth,
},
}
}
pub fn level_extent(&self, level: Level) -> Extent {
use std::cmp::{max, min};
let map = |val| max(min(val, 1), val >> min(level, MAX_LEVEL));
match *self {
Kind::D1(w, _) => Extent {
width: map(w),
height: 1,
depth: 1,
},
Kind::D2(w, h, _, _) => Extent {
width: map(w),
height: map(h),
depth: 1,
},
Kind::D3(w, h, d) => Extent {
width: map(w),
height: map(h),
depth: map(d),
},
}
}
pub fn num_levels(&self) -> Level {
use std::cmp::max;
match *self {
Kind::D2(_, _, _, s) if s > 1 => {
1
}
_ => {
let extent = self.extent();
let dominant = max(max(extent.width, extent.height), extent.depth);
(1..).find(|level| dominant >> level == 0).unwrap()
}
}
}
pub fn num_layers(&self) -> Layer {
match *self {
Kind::D1(_, a) | Kind::D2(_, _, a, _) => a,
Kind::D3(..) => 1,
}
}
pub fn num_samples(&self) -> NumSamples {
match *self {
Kind::D1(..) => 1,
Kind::D2(_, _, _, s) => s,
Kind::D3(..) => 1,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ViewKind {
D1,
D1Array,
D2,
D2Array,
D3,
Cube,
CubeArray,
}
bitflags!(
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ViewCapabilities: u32 {
const MUTABLE_FORMAT = 0x0000_0008;
const KIND_CUBE = 0x0000_0010;
const KIND_2D_ARRAY = 0x0000_0020;
}
);
bitflags!(
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Usage: u32 {
const TRANSFER_SRC = 0x1;
const TRANSFER_DST = 0x2;
const SAMPLED = 0x4;
const STORAGE = 0x8;
const COLOR_ATTACHMENT = 0x10;
const DEPTH_STENCIL_ATTACHMENT = 0x20;
const TRANSIENT_ATTACHMENT = 0x40;
const INPUT_ATTACHMENT = 0x80;
}
);
impl Usage {
pub fn can_transfer(&self) -> bool {
self.intersects(Usage::TRANSFER_SRC | Usage::TRANSFER_DST)
}
pub fn can_target(&self) -> bool {
self.intersects(Usage::COLOR_ATTACHMENT | Usage::DEPTH_STENCIL_ATTACHMENT)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum WrapMode {
Tile,
Mirror,
Clamp,
Border,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Lod(i16);
impl From<f32> for Lod {
fn from(v: f32) -> Lod {
Lod((v * 8.0) as i16)
}
}
impl Into<f32> for Lod {
fn into(self) -> f32 {
self.0 as f32 / 8.0
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PackedColor(pub u32);
impl From<[f32; 4]> for PackedColor {
fn from(c: [f32; 4]) -> PackedColor {
PackedColor(
c.iter()
.rev()
.fold(0, |u, &c| (u << 8) + (c * 255.0) as u32),
)
}
}
impl Into<[f32; 4]> for PackedColor {
fn into(self) -> [f32; 4] {
let mut out = [0.0; 4];
for (i, channel) in out.iter_mut().enumerate() {
let byte = (self.0 >> (i << 3)) & 0xFF;
*channel = byte as f32 / 255.0;
}
out
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SamplerInfo {
pub min_filter: Filter,
pub mag_filter: Filter,
pub mip_filter: Filter,
pub wrap_mode: (WrapMode, WrapMode, WrapMode),
pub lod_bias: Lod,
pub lod_range: Range<Lod>,
pub comparison: Option<Comparison>,
pub border: PackedColor,
pub anisotropic: Anisotropic,
}
impl SamplerInfo {
pub fn new(filter: Filter, wrap: WrapMode) -> Self {
SamplerInfo {
min_filter: filter,
mag_filter: filter,
mip_filter: filter,
wrap_mode: (wrap, wrap, wrap),
lod_bias: Lod(0),
lod_range: Lod(-8000)..Lod(8000),
comparison: None,
border: PackedColor(0),
anisotropic: Anisotropic::Off,
}
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Layout {
General,
ColorAttachmentOptimal,
DepthStencilAttachmentOptimal,
DepthStencilReadOnlyOptimal,
ShaderReadOnlyOptimal,
TransferSrcOptimal,
TransferDstOptimal,
Undefined, Preinitialized,
Present,
}
bitflags!(
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Access: u32 {
const INPUT_ATTACHMENT_READ = 0x10;
const SHADER_READ = 0x20;
const SHADER_WRITE = 0x40;
const COLOR_ATTACHMENT_READ = 0x80;
const COLOR_ATTACHMENT_WRITE = 0x100;
const DEPTH_STENCIL_ATTACHMENT_READ = 0x200;
const DEPTH_STENCIL_ATTACHMENT_WRITE = 0x400;
const TRANSFER_READ = 0x800;
const TRANSFER_WRITE = 0x1000;
const HOST_READ = 0x2000;
const HOST_WRITE = 0x4000;
const MEMORY_READ = 0x8000;
const MEMORY_WRITE = 0x10000;
}
);
pub type State = (Access, Layout);
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Subresource {
pub aspects: format::Aspects,
pub level: Level,
pub layer: Layer,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubresourceLayers {
pub aspects: format::Aspects,
pub level: Level,
pub layers: Range<Layer>,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubresourceRange {
pub aspects: format::Aspects,
pub levels: Range<Level>,
pub layers: Range<Layer>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct FormatProperties {
pub max_extent: Extent,
pub max_levels: Level,
pub max_layers: Layer,
pub sample_count_mask: NumSamples,
pub max_resource_size: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubresourceFootprint {
pub slice: Range<RawOffset>,
pub row_pitch: RawOffset,
pub array_pitch: RawOffset,
pub depth_pitch: RawOffset,
}