#![warn(missing_docs)]
use crate::{define_shared_wrapper, error::FrameworkError};
use fyrox_core::define_as_any_trait;
#[derive(Copy, Clone)]
pub enum GpuTextureKind {
Line {
length: usize,
},
Rectangle {
width: usize,
height: usize,
},
Cube {
size: usize,
},
Volume {
width: usize,
height: usize,
depth: usize,
},
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum PixelKind {
R32F,
R32UI,
R16F,
D32F,
D16,
D24S8,
RGBA8,
SRGBA8,
RGB8,
SRGB8,
BGRA8,
BGR8,
RG8,
LA8,
LA16,
RG16,
RG16F,
R8,
L8,
L16,
R8UI,
R16,
RGB16,
RGBA16,
DXT1RGB,
DXT1RGBA,
DXT3RGBA,
DXT5RGBA,
RGB32F,
RGBA32F,
RGB16F,
RGBA16F,
R8RGTC,
RG8RGTC,
R11G11B10F,
RGB10A2,
}
pub enum PixelElementKind {
Float,
NormalizedUnsignedInteger,
Integer,
UnsignedInteger,
}
impl PixelKind {
#[doc(hidden)]
pub fn unpack_alignment(self) -> Option<i32> {
match self {
Self::RGBA16
| Self::RGBA16F
| Self::RGB16
| Self::RGB16F
| Self::RGBA32F
| Self::RGB32F
| Self::RGBA8
| Self::SRGBA8
| Self::BGRA8
| Self::RG16
| Self::RG16F
| Self::LA16
| Self::D24S8
| Self::D32F
| Self::R32F
| Self::R32UI
| Self::RGB10A2 => Some(4),
Self::RG8 | Self::LA8 | Self::D16 | Self::R16F | Self::L16 | Self::R16 => Some(2),
Self::R8
| Self::L8
| Self::R8UI
| Self::SRGB8
| Self::RGB8
| Self::BGR8
| Self::R11G11B10F => Some(1),
Self::DXT1RGB
| Self::DXT1RGBA
| Self::DXT3RGBA
| Self::DXT5RGBA
| Self::R8RGTC
| Self::RG8RGTC => None,
}
}
pub fn is_compressed(self) -> bool {
match self {
Self::DXT1RGB
| Self::DXT1RGBA
| Self::DXT3RGBA
| Self::DXT5RGBA
| Self::R8RGTC
| Self::RG8RGTC => true,
Self::RGBA16
| Self::RGBA16F
| Self::RGB16
| Self::RGB16F
| Self::RGBA8
| Self::SRGBA8
| Self::RGB8
| Self::SRGB8
| Self::BGRA8
| Self::BGR8
| Self::RG16
| Self::RG16F
| Self::R16
| Self::D24S8
| Self::D32F
| Self::R32F
| Self::R32UI
| Self::RG8
| Self::D16
| Self::R16F
| Self::R8
| Self::R8UI
| Self::RGB32F
| Self::RGBA32F
| Self::R11G11B10F
| Self::RGB10A2
| Self::L8
| Self::LA8
| Self::L16
| Self::LA16 => false,
}
}
pub fn element_kind(self) -> PixelElementKind {
match self {
Self::R32F
| Self::R16F
| Self::RG16F
| Self::RGB32F
| Self::RGBA32F
| Self::RGBA16F
| Self::RGB16F
| Self::D32F
| Self::R11G11B10F => PixelElementKind::Float,
Self::D16
| Self::D24S8
| Self::RGBA8
| Self::SRGBA8
| Self::RGB8
| Self::SRGB8
| Self::BGRA8
| Self::BGR8
| Self::RG8
| Self::RG16
| Self::R8
| Self::R16
| Self::RGB16
| Self::RGBA16
| Self::DXT1RGB
| Self::DXT1RGBA
| Self::DXT3RGBA
| Self::DXT5RGBA
| Self::R8RGTC
| Self::RG8RGTC
| Self::RGB10A2
| Self::LA8
| Self::L8
| Self::LA16
| Self::L16 => PixelElementKind::NormalizedUnsignedInteger,
Self::R8UI | Self::R32UI => PixelElementKind::UnsignedInteger,
}
}
}
fn ceil_div_4(x: usize) -> usize {
x.div_ceil(4)
}
pub fn image_3d_size_bytes(
pixel_kind: PixelKind,
width: usize,
height: usize,
depth: usize,
) -> usize {
let pixel_count = width * height * depth;
match pixel_kind {
PixelKind::RGBA32F => 16 * pixel_count,
PixelKind::RGB32F => 12 * pixel_count,
PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
PixelKind::RGBA8
| PixelKind::SRGBA8
| PixelKind::BGRA8
| PixelKind::RG16
| PixelKind::RG16F
| PixelKind::LA16
| PixelKind::D24S8
| PixelKind::D32F
| PixelKind::R32F
| PixelKind::R32UI
| PixelKind::R11G11B10F
| PixelKind::RGB10A2 => 4 * pixel_count,
PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
PixelKind::RG8
| PixelKind::LA8
| PixelKind::R16
| PixelKind::L16
| PixelKind::D16
| PixelKind::R16F => 2 * pixel_count,
PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
let block_size = 8;
ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
}
PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
let block_size = 16;
ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
}
}
}
pub fn image_2d_size_bytes(pixel_kind: PixelKind, width: usize, height: usize) -> usize {
let pixel_count = width * height;
match pixel_kind {
PixelKind::RGBA32F => 16 * pixel_count,
PixelKind::RGB32F => 12 * pixel_count,
PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
PixelKind::RGBA8
| PixelKind::SRGBA8
| PixelKind::BGRA8
| PixelKind::RG16
| PixelKind::RG16F
| PixelKind::LA16
| PixelKind::D24S8
| PixelKind::D32F
| PixelKind::R32F
| PixelKind::R32UI
| PixelKind::R11G11B10F
| PixelKind::RGB10A2 => 4 * pixel_count,
PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
PixelKind::RG8
| PixelKind::LA8
| PixelKind::R16
| PixelKind::L16
| PixelKind::D16
| PixelKind::R16F => 2 * pixel_count,
PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
let block_size = 8;
ceil_div_4(width) * ceil_div_4(height) * block_size
}
PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
let block_size = 16;
ceil_div_4(width) * ceil_div_4(height) * block_size
}
}
}
pub fn image_1d_size_bytes(pixel_kind: PixelKind, length: usize) -> usize {
match pixel_kind {
PixelKind::RGBA32F => 16 * length,
PixelKind::RGB32F => 12 * length,
PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * length,
PixelKind::RGB16 | PixelKind::RGB16F => 6 * length,
PixelKind::RGBA8
| PixelKind::SRGBA8
| PixelKind::BGRA8
| PixelKind::RG16
| PixelKind::RG16F
| PixelKind::LA16
| PixelKind::D24S8
| PixelKind::D32F
| PixelKind::R32F
| PixelKind::R32UI
| PixelKind::R11G11B10F
| PixelKind::RGB10A2 => 4 * length,
PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * length,
PixelKind::RG8
| PixelKind::LA8
| PixelKind::L16
| PixelKind::R16
| PixelKind::D16
| PixelKind::R16F => 2 * length,
PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => length,
PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
let block_size = 8;
ceil_div_4(length) * block_size
}
PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
let block_size = 16;
ceil_div_4(length) * block_size
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum CubeMapFace {
PositiveX,
NegativeX,
PositiveY,
NegativeY,
PositiveZ,
NegativeZ,
}
pub struct GpuTextureDescriptor<'a> {
pub name: &'a str,
pub kind: GpuTextureKind,
pub pixel_kind: PixelKind,
pub mip_count: usize,
pub data: Option<&'a [u8]>,
pub base_level: usize,
pub max_level: usize,
}
impl Default for GpuTextureDescriptor<'_> {
fn default() -> Self {
Self {
name: "",
kind: GpuTextureKind::Rectangle {
width: 1,
height: 1,
},
pixel_kind: PixelKind::RGBA8,
mip_count: 1,
data: None,
base_level: 0,
max_level: 1000,
}
}
}
define_as_any_trait!(GpuTextureAsAny => GpuTextureTrait);
pub trait GpuTextureTrait: GpuTextureAsAny {
fn set_data(
&self,
kind: GpuTextureKind,
pixel_kind: PixelKind,
mip_count: usize,
data: Option<&[u8]>,
) -> Result<usize, FrameworkError>;
fn kind(&self) -> GpuTextureKind;
fn pixel_kind(&self) -> PixelKind;
}
define_shared_wrapper!(GpuTexture<dyn GpuTextureTrait>);