bitflags!(
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aspects: u8 {
const COLOR = 0x1;
const DEPTH = 0x2;
const STENCIL = 0x4;
}
);
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FormatDesc {
pub bits: u16,
pub dim: (u8, u8),
pub packed: bool,
pub aspects: Aspects,
}
impl FormatDesc {
pub fn is_compressed(&self) -> bool {
self.dim != (1, 1)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct FormatBits {
pub color: u8,
pub alpha: u8,
pub depth: u8,
pub stencil: u8,
}
pub const BITS_ZERO: FormatBits = FormatBits {
color: 0,
alpha: 0,
depth: 0,
stencil: 0,
};
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Component {
Zero = 1,
One = 2,
R = 3,
G = 4,
B = 5,
A = 6,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Swizzle(pub Component, pub Component, pub Component, pub Component);
impl Swizzle {
pub const NO: Swizzle = Swizzle(Component::R, Component::G, Component::B, Component::A);
}
impl Default for Swizzle {
fn default() -> Self {
Self::NO
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Properties {
pub linear_tiling: ImageFeature,
pub optimal_tiling: ImageFeature,
pub buffer_features: BufferFeature,
}
bitflags!(
#[derive(Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ImageFeature: u32 {
const SAMPLED = 0x1;
const STORAGE = 0x2;
const STORAGE_ATOMIC = 0x4;
const COLOR_ATTACHMENT = 0x80;
const COLOR_ATTACHMENT_BLEND = 0x100;
const DEPTH_STENCIL_ATTACHMENT = 0x200;
const BLIT_SRC = 0x400;
const BLIT_DST = 0x800;
const SAMPLED_LINEAR = 0x1000;
}
);
bitflags!(
#[derive(Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BufferFeature: u32 {
const UNIFORM_TEXEL = 0x8;
const STORAGE_TEXEL = 0x10;
const STORAGE_TEXEL_ATOMIC = 0x20;
const VERTEX = 0x40;
}
);
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ChannelType {
Unorm,
Snorm,
Uint,
Sint,
Ufloat,
Sfloat,
Uscaled,
Sscaled,
Srgb,
}
macro_rules! surface_types {
{ $($name:ident { $total:expr, $($aspect:ident)|*, $dim:expr $( ,$component:ident : $bits:expr )*} ,)* } => {
#[repr(u8)]
#[allow(missing_docs, non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum SurfaceType {
$( $name, )*
}
impl SurfaceType {
pub fn describe_bits(&self) -> FormatBits {
match *self {
$( SurfaceType::$name => FormatBits {
$( $component: $bits, )*
.. BITS_ZERO
}, )*
}
}
pub fn desc(&self) -> FormatDesc {
match *self {
$( SurfaceType::$name => FormatDesc {
bits: $total.min(!$total),
dim: $dim,
packed: $total > 0x1000,
aspects: $(Aspects::$aspect)|*,
}, )*
}
}
}
}
}
surface_types! {
R4_G4 { !8, COLOR, (1, 1), color: 8 },
R4_G4_B4_A4 { !16, COLOR, (1, 1), color: 12, alpha: 4 },
B4_G4_R4_A4 { !16, COLOR, (1, 1), color: 12, alpha: 4 },
R5_G6_B5 { !16, COLOR, (1, 1), color: 16 },
B5_G6_R5 { !16, COLOR, (1, 1), color: 16 },
R5_G5_B5_A1 { !16, COLOR, (1, 1), color: 15, alpha: 1 },
B5_G5_R5_A1 { !16, COLOR, (1, 1), color: 15, alpha: 1 },
A1_R5_G5_B5 { !16, COLOR, (1, 1), color: 15, alpha: 1 },
R8 { 8, COLOR, (1, 1), color: 8 },
R8_G8 { 16, COLOR, (1, 1), color: 16 },
R8_G8_B8 { 24, COLOR, (1, 1), color: 24 },
B8_G8_R8 { 24, COLOR, (1, 1), color: 24 },
R8_G8_B8_A8 { 32, COLOR, (1, 1), color: 24, alpha: 8 },
B8_G8_R8_A8 { 32, COLOR, (1, 1), color: 24, alpha: 8 },
A8_B8_G8_R8 { !32, COLOR, (1, 1), color: 24, alpha: 8 },
A2_R10_G10_B10 { !32, COLOR, (1, 1), color: 30, alpha: 2 },
A2_B10_G10_R10 { !32, COLOR, (1, 1), color: 30, alpha: 2 },
R16 { 16, COLOR, (1, 1), color: 16 },
R16_G16 { 32, COLOR, (1, 1), color: 32 },
R16_G16_B16 { 48, COLOR, (1, 1), color: 48 },
R16_G16_B16_A16 { 64, COLOR, (1, 1), color: 48, alpha: 16 },
R32 { 32, COLOR, (1, 1), color: 32 },
R32_G32 { 64, COLOR, (1, 1), color: 64 },
R32_G32_B32 { 96, COLOR, (1, 1), color: 96 },
R32_G32_B32_A32 { 128, COLOR, (1, 1), color: 96, alpha: 32 },
R64 { 64, COLOR, (1, 1), color: 64 },
R64_G64 { 128, COLOR, (1, 1), color: 128 },
R64_G64_B64 { 192, COLOR, (1, 1), color: 192 },
R64_G64_B64_A64 { 256, COLOR, (1, 1), color: 192, alpha: 64 },
B10_G11_R11 { !32, COLOR, (1, 1), color: 32 },
E5_B9_G9_R9 { !32, COLOR, (1, 1), color: 27 },
D16 { 16, DEPTH, (1, 1), depth: 16 },
X8D24 { !32, DEPTH, (1, 1), depth: 24 },
D32 { 32, DEPTH, (1, 1), depth: 32 },
S8 { 8, STENCIL, (1, 1), stencil: 8 },
D16_S8 { 24, DEPTH | STENCIL, (1, 1), depth: 16, stencil: 8 },
D24_S8 { 32, DEPTH | STENCIL, (1, 1), depth: 24, stencil: 8 },
D32_S8 { 40, DEPTH | STENCIL, (1, 1), depth: 32, stencil: 8 },
BC1_RGB { 64, COLOR, (4, 4) },
BC1_RGBA { 64, COLOR, (4, 4) },
BC2 { 128, COLOR, (4, 4) },
BC3 { 128, COLOR, (4, 4) },
BC4 { 64, COLOR, (4, 4) },
BC5 { 128, COLOR, (4, 4) },
BC6 { 128, COLOR, (4, 4) },
BC7 { 128, COLOR, (4, 4) },
ETC2_R8_G8_B8 { 64, COLOR, (4, 4) },
ETC2_R8_G8_B8_A1 { 64, COLOR, (4, 4) },
ETC2_R8_G8_B8_A8 { 128, COLOR, (4, 4) },
EAC_R11 { 64, COLOR, (4, 4) },
EAC_R11_G11 { 128, COLOR, (4, 4) },
ASTC_4x4 { 128, COLOR, (4, 4) },
ASTC_5x4 { 128, COLOR, (5, 4) },
ASTC_5x5 { 128, COLOR, (5, 5) },
ASTC_6x5 { 128, COLOR, (6, 5) },
ASTC_6x6 { 128, COLOR, (6, 6) },
ASTC_8x5 { 128, COLOR, (8, 5) },
ASTC_8x6 { 128, COLOR, (8, 6) },
ASTC_8x8 { 128, COLOR, (8, 8) },
ASTC_10x5 { 128, COLOR, (10, 5) },
ASTC_10x6 { 128, COLOR, (10, 6) },
ASTC_10x8 { 128, COLOR, (10, 8) },
ASTC_10x10 { 128, COLOR, (10, 10) },
ASTC_12x10 { 128, COLOR, (12, 10) },
ASTC_12x12 { 128, COLOR, (12, 12) },
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BaseFormat(pub SurfaceType, pub ChannelType);
pub trait AsFormat {
const SELF: Format;
}
macro_rules! formats {
{
$name:ident = ($surface:ident, $channel:ident),
$($name_tail:ident = ($surface_tail:ident, $channel_tail:ident),)*
} => {
#[allow(missing_docs)]
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Format {
$name = 1,
$( $name_tail, )*
#[doc(hidden)]
__NumFormats,
}
pub const NUM_FORMATS: usize = Format::__NumFormats as _;
pub const BASE_FORMATS: [BaseFormat; NUM_FORMATS-1] = [
BaseFormat(SurfaceType::$surface, ChannelType::$channel),
$(BaseFormat(SurfaceType::$surface_tail, ChannelType::$channel_tail), )*
];
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct $name;
impl AsFormat for $name {
const SELF: Format = Format::$name;
}
$(
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct $name_tail;
impl AsFormat for $name_tail {
const SELF: Format = Format::$name_tail;
}
)*
}
}
formats! {
Rg4Unorm = (R4_G4, Unorm),
Rgba4Unorm = (R4_G4_B4_A4, Unorm),
Bgra4Unorm = (B4_G4_R4_A4, Unorm),
R5g6b5Unorm = (R5_G6_B5, Unorm),
B5g6r5Unorm = (B5_G6_R5, Unorm),
R5g5b5a1Unorm = (R5_G5_B5_A1, Unorm),
B5g5r5a1Unorm = (B5_G5_R5_A1, Unorm),
A1r5g5b5Unorm = (A1_R5_G5_B5, Unorm),
R8Unorm = (R8, Unorm),
R8Snorm = (R8, Snorm),
R8Uscaled = (R8, Uscaled),
R8Sscaled = (R8, Sscaled),
R8Uint = (R8, Uint),
R8Sint = (R8, Sint),
R8Srgb = (R8, Srgb),
Rg8Unorm = (R8_G8, Unorm),
Rg8Snorm = (R8_G8, Snorm),
Rg8Uscaled = (R8_G8, Uscaled),
Rg8Sscaled = (R8_G8, Sscaled),
Rg8Uint = (R8_G8, Uint),
Rg8Sint = (R8_G8, Sint),
Rg8Srgb = (R8_G8, Srgb),
Rgb8Unorm = (R8_G8_B8, Unorm),
Rgb8Snorm = (R8_G8_B8, Snorm),
Rgb8Uscaled = (R8_G8_B8, Uscaled),
Rgb8Sscaled = (R8_G8_B8, Sscaled),
Rgb8Uint = (R8_G8_B8, Uint),
Rgb8Sint = (R8_G8_B8, Sint),
Rgb8Srgb = (R8_G8_B8, Srgb),
Bgr8Unorm = (B8_G8_R8, Unorm),
Bgr8Snorm = (B8_G8_R8, Snorm),
Bgr8Uscaled = (B8_G8_R8, Uscaled),
Bgr8Sscaled = (B8_G8_R8, Sscaled),
Bgr8Uint = (B8_G8_R8, Uint),
Bgr8Sint = (B8_G8_R8, Sint),
Bgr8Srgb = (B8_G8_R8, Srgb),
Rgba8Unorm = (R8_G8_B8_A8, Unorm),
Rgba8Snorm = (R8_G8_B8_A8, Snorm),
Rgba8Uscaled = (R8_G8_B8_A8, Uscaled),
Rgba8Sscaled = (R8_G8_B8_A8, Sscaled),
Rgba8Uint = (R8_G8_B8_A8, Uint),
Rgba8Sint = (R8_G8_B8_A8, Sint),
Rgba8Srgb = (R8_G8_B8_A8, Srgb),
Bgra8Unorm = (B8_G8_R8_A8, Unorm),
Bgra8Snorm = (B8_G8_R8_A8, Snorm),
Bgra8Uscaled = (B8_G8_R8_A8, Uscaled),
Bgra8Sscaled = (B8_G8_R8_A8, Sscaled),
Bgra8Uint = (B8_G8_R8_A8, Uint),
Bgra8Sint = (B8_G8_R8_A8, Sint),
Bgra8Srgb = (B8_G8_R8_A8, Srgb),
Abgr8Unorm = (A8_B8_G8_R8, Unorm),
Abgr8Snorm = (A8_B8_G8_R8, Snorm),
Abgr8Uscaled = (A8_B8_G8_R8, Uscaled),
Abgr8Sscaled = (A8_B8_G8_R8, Sscaled),
Abgr8Uint = (A8_B8_G8_R8, Uint),
Abgr8Sint = (A8_B8_G8_R8, Sint),
Abgr8Srgb = (A8_B8_G8_R8, Srgb),
A2r10g10b10Unorm = (A2_R10_G10_B10, Unorm),
A2r10g10b10Snorm = (A2_R10_G10_B10, Snorm),
A2r10g10b10Uscaled = (A2_R10_G10_B10, Uscaled),
A2r10g10b10Sscaled = (A2_R10_G10_B10, Sscaled),
A2r10g10b10Uint = (A2_R10_G10_B10, Uint),
A2r10g10b10Sint = (A2_R10_G10_B10, Sint),
A2b10g10r10Unorm = (A2_B10_G10_R10, Unorm),
A2b10g10r10Snorm = (A2_B10_G10_R10, Snorm),
A2b10g10r10Uscaled = (A2_B10_G10_R10, Uscaled),
A2b10g10r10Sscaled = (A2_B10_G10_R10, Sscaled),
A2b10g10r10Uint = (A2_B10_G10_R10, Uint),
A2b10g10r10Sint = (A2_B10_G10_R10, Sint),
R16Unorm = (R16, Unorm),
R16Snorm = (R16, Snorm),
R16Uscaled = (R16, Uscaled),
R16Sscaled = (R16, Sscaled),
R16Uint = (R16, Uint),
R16Sint = (R16, Sint),
R16Sfloat = (R16, Sfloat),
Rg16Unorm = (R16_G16, Unorm),
Rg16Snorm = (R16_G16, Snorm),
Rg16Uscaled = (R16_G16, Uscaled),
Rg16Sscaled = (R16_G16, Sscaled),
Rg16Uint = (R16_G16, Uint),
Rg16Sint = (R16_G16, Sint),
Rg16Sfloat = (R16_G16, Sfloat),
Rgb16Unorm = (R16_G16_B16, Unorm),
Rgb16Snorm = (R16_G16_B16, Snorm),
Rgb16Uscaled = (R16_G16_B16, Uscaled),
Rgb16Sscaled = (R16_G16_B16, Sscaled),
Rgb16Uint = (R16_G16_B16, Uint),
Rgb16Sint = (R16_G16_B16, Sint),
Rgb16Sfloat = (R16_G16_B16, Sfloat),
Rgba16Unorm = (R16_G16_B16_A16, Unorm),
Rgba16Snorm = (R16_G16_B16_A16, Snorm),
Rgba16Uscaled = (R16_G16_B16_A16, Uscaled),
Rgba16Sscaled = (R16_G16_B16_A16, Sscaled),
Rgba16Uint = (R16_G16_B16_A16, Uint),
Rgba16Sint = (R16_G16_B16_A16, Sint),
Rgba16Sfloat = (R16_G16_B16_A16, Sfloat),
R32Uint = (R32, Uint),
R32Sint = (R32, Sint),
R32Sfloat = (R32, Sfloat),
Rg32Uint = (R32_G32, Uint),
Rg32Sint = (R32_G32, Sint),
Rg32Sfloat = (R32_G32, Sfloat),
Rgb32Uint = (R32_G32_B32, Uint),
Rgb32Sint = (R32_G32_B32, Sint),
Rgb32Sfloat = (R32_G32_B32, Sfloat),
Rgba32Uint = (R32_G32_B32_A32, Uint),
Rgba32Sint = (R32_G32_B32_A32, Sint),
Rgba32Sfloat = (R32_G32_B32_A32, Sfloat),
R64Uint = (R64, Uint),
R64Sint = (R64, Sint),
R64Sfloat = (R64, Sfloat),
Rg64Uint = (R64_G64, Uint),
Rg64Sint = (R64_G64, Sint),
Rg64Sfloat = (R64_G64, Sfloat),
Rgb64Uint = (R64_G64_B64, Uint),
Rgb64Sint = (R64_G64_B64, Sint),
Rgb64Sfloat = (R64_G64_B64, Sfloat),
Rgba64Uint = (R64_G64_B64_A64, Uint),
Rgba64Sint = (R64_G64_B64_A64, Sint),
Rgba64Sfloat = (R64_G64_B64_A64, Sfloat),
B10g11r11Ufloat = (B10_G11_R11, Ufloat),
E5b9g9r9Ufloat = (E5_B9_G9_R9, Ufloat),
D16Unorm = (D16, Unorm),
X8D24Unorm = (X8D24, Unorm),
D32Sfloat = (D32, Sfloat),
S8Uint = (S8, Uint),
D16UnormS8Uint = (D16_S8, Unorm),
D24UnormS8Uint = (D24_S8, Unorm),
D32SfloatS8Uint = (D32_S8, Sfloat),
Bc1RgbUnorm = (BC1_RGB, Unorm),
Bc1RgbSrgb = (BC1_RGB, Srgb),
Bc1RgbaUnorm = (BC1_RGBA, Unorm),
Bc1RgbaSrgb = (BC1_RGBA, Srgb),
Bc2Unorm = (BC2, Unorm),
Bc2Srgb = (BC2, Srgb),
Bc3Unorm = (BC3, Unorm),
Bc3Srgb = (BC3, Srgb),
Bc4Unorm = (BC4, Unorm),
Bc4Snorm = (BC4, Snorm),
Bc5Unorm = (BC5, Unorm),
Bc5Snorm = (BC5, Snorm),
Bc6hUfloat = (BC6, Ufloat),
Bc6hSfloat = (BC6, Sfloat),
Bc7Unorm = (BC7, Unorm),
Bc7Srgb = (BC7, Srgb),
Etc2R8g8b8Unorm = (ETC2_R8_G8_B8, Unorm),
Etc2R8g8b8Srgb = (ETC2_R8_G8_B8, Srgb),
Etc2R8g8b8a1Unorm = (ETC2_R8_G8_B8_A1, Unorm),
Etc2R8g8b8a1Srgb = (ETC2_R8_G8_B8_A1, Srgb),
Etc2R8g8b8a8Unorm = (ETC2_R8_G8_B8_A8, Unorm),
Etc2R8g8b8a8Srgb = (ETC2_R8_G8_B8_A8, Srgb),
EacR11Unorm = (EAC_R11, Unorm),
EacR11Snorm = (EAC_R11, Snorm),
EacR11g11Unorm = (EAC_R11_G11, Unorm),
EacR11g11Snorm = (EAC_R11_G11, Snorm),
Astc4x4Unorm = (ASTC_4x4, Unorm),
Astc4x4Srgb = (ASTC_4x4, Srgb),
Astc5x4Unorm = (ASTC_5x4, Unorm),
Astc5x4Srgb = (ASTC_5x4, Srgb),
Astc5x5Unorm = (ASTC_5x5, Unorm),
Astc5x5Srgb = (ASTC_5x5, Srgb),
Astc6x5Unorm = (ASTC_6x5, Unorm),
Astc6x5Srgb = (ASTC_6x5, Srgb),
Astc6x6Unorm = (ASTC_6x6, Unorm),
Astc6x6Srgb = (ASTC_6x6, Srgb),
Astc8x5Unorm = (ASTC_8x5, Unorm),
Astc8x5Srgb = (ASTC_8x5, Srgb),
Astc8x6Unorm = (ASTC_8x6, Unorm),
Astc8x6Srgb = (ASTC_8x6, Srgb),
Astc8x8Unorm = (ASTC_8x8, Unorm),
Astc8x8Srgb = (ASTC_8x8, Srgb),
Astc10x5Unorm = (ASTC_10x5, Unorm),
Astc10x5Srgb = (ASTC_10x5, Srgb),
Astc10x6Unorm = (ASTC_10x6, Unorm),
Astc10x6Srgb = (ASTC_10x6, Srgb),
Astc10x8Unorm = (ASTC_10x8, Unorm),
Astc10x8Srgb = (ASTC_10x8, Srgb),
Astc10x10Unorm = (ASTC_10x10, Unorm),
Astc10x10Srgb = (ASTC_10x10, Srgb),
Astc12x10Unorm = (ASTC_12x10, Unorm),
Astc12x10Srgb = (ASTC_12x10, Srgb),
Astc12x12Unorm = (ASTC_12x12, Unorm),
Astc12x12Srgb = (ASTC_12x12, Srgb),
}
impl Format {
pub fn base_format(self) -> BaseFormat {
assert!(self as usize != 0 && NUM_FORMATS > self as usize);
BASE_FORMATS[self as usize - 1]
}
pub fn surface_desc(&self) -> FormatDesc {
self.base_format().0.desc()
}
pub fn is_color(self) -> bool {
self.surface_desc().aspects.contains(Aspects::COLOR)
}
pub fn is_depth(self) -> bool {
self.surface_desc().aspects.contains(Aspects::DEPTH)
}
pub fn is_stencil(self) -> bool {
self.surface_desc().aspects.contains(Aspects::STENCIL)
}
}
impl AsFormat for f32 {
const SELF: Format = Format::R32Sfloat;
}
impl AsFormat for [f32; 2] {
const SELF: Format = Format::Rg32Sfloat;
}
impl AsFormat for [f32; 3] {
const SELF: Format = Format::Rgb32Sfloat;
}
impl AsFormat for [f32; 4] {
const SELF: Format = Format::Rgba32Sfloat;
}