diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index 331c6213bd..14ee9ca52d 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -44,6 +44,10 @@ pub enum TransferError { UnalignedCopyWidth, #[error("copy height is not a multiple of block height")] UnalignedCopyHeight, + #[error("copy origin's x component is not a multiple of block width")] + UnalignedCopyOriginX, + #[error("copy origin's y component is not a multiple of block height")] + UnalignedCopyOriginY, #[error("bytes per row does not respect `COPY_BYTES_PER_ROW_ALIGNMENT`")] UnalignedBytesPerRow, #[error("number of rows per image is not a multiple of block height")] @@ -103,8 +107,9 @@ pub(crate) fn texture_copy_view_to_hal( /// Function copied with minor modifications from webgpu standard https://gpuweb.github.io/gpuweb/#valid-texture-copy-range pub(crate) fn validate_linear_texture_data( layout: &TextureDataLayout, + format: wgt::TextureFormat, buffer_size: BufferAddress, - bytes_per_texel: BufferAddress, + bytes_per_block: BufferAddress, copy_size: &Extent3d, ) -> Result { // Convert all inputs to BufferAddress (u64) to prevent overflow issues @@ -116,10 +121,10 @@ pub(crate) fn validate_linear_texture_data( let rows_per_image = layout.rows_per_image as BufferAddress; let bytes_per_row = layout.bytes_per_row as BufferAddress; - // TODO: Once compressed textures are supported, these needs to be fixed - let block_width: BufferAddress = 1; - let block_height: BufferAddress = 1; - let block_size = bytes_per_texel; + let (block_width, block_height) = conv::texture_block_size(format); + let block_width = block_width as BufferAddress; + let block_height = block_height as BufferAddress; + let block_size = bytes_per_block; if copy_width % block_width != 0 { return Err(TransferError::UnalignedCopyWidth); @@ -168,12 +173,11 @@ pub(crate) fn validate_linear_texture_data( /// Function copied with minor modifications from webgpu standard https://gpuweb.github.io/gpuweb/#valid-texture-copy-range pub(crate) fn validate_texture_copy_range( texture_copy_view: &TextureCopyView, + texture_format: wgt::TextureFormat, texture_dimension: hal::image::Kind, copy_size: &Extent3d, ) -> Result { - // TODO: Once compressed textures are supported, these needs to be fixed - let block_width: u32 = 1; - let block_height: u32 = 1; + let (block_width, block_height) = conv::texture_block_size(texture_format); let mut extent = texture_dimension.level_extent(texture_copy_view.mip_level as u8); match texture_dimension { @@ -201,6 +205,12 @@ pub(crate) fn validate_texture_copy_range( return Err(TransferError::BufferOverrun); } + if texture_copy_view.origin.x % block_width != 0 { + return Err(TransferError::UnalignedCopyOriginX); + } + if texture_copy_view.origin.y % block_height != 0 { + return Err(TransferError::UnalignedCopyOriginY); + } if copy_size.width % block_width != 0 { return Err(TransferError::UnalignedCopyWidth); } @@ -359,26 +369,29 @@ impl Global { let dst_barriers = dst_pending.map(|pending| pending.into_hal(dst_texture)); let bytes_per_row_alignment = wgt::COPY_BYTES_PER_ROW_ALIGNMENT; - let bytes_per_texel = conv::map_texture_format(dst_texture.format, cmb.private_features) + let bytes_per_block = conv::map_texture_format(dst_texture.format, cmb.private_features) .surface_desc() .bits as u32 / BITS_PER_BYTE; let src_bytes_per_row = source.layout.bytes_per_row; - if bytes_per_row_alignment % bytes_per_texel != 0 { + if bytes_per_row_alignment % bytes_per_block != 0 { return Err(TransferError::UnalignedBytesPerRow); } if src_bytes_per_row % bytes_per_row_alignment != 0 { return Err(TransferError::UnalignedBytesPerRow); } - validate_texture_copy_range(destination, dst_texture.kind, copy_size)?; + validate_texture_copy_range(destination, dst_texture.format, dst_texture.kind, copy_size)?; validate_linear_texture_data( &source.layout, + dst_texture.format, src_buffer.size, - bytes_per_texel as BufferAddress, + bytes_per_block as BufferAddress, copy_size, )?; - let buffer_width = source.layout.bytes_per_row / bytes_per_texel; + let (block_width, _) = conv::texture_block_size(dst_texture.format); + + let buffer_width = (source.layout.bytes_per_row / bytes_per_block) * block_width; let region = hal::command::BufferImageCopy { buffer_offset: source.layout.offset, buffer_width, @@ -459,26 +472,29 @@ impl Global { let dst_barrier = dst_barriers.map(|pending| pending.into_hal(dst_buffer)); let bytes_per_row_alignment = wgt::COPY_BYTES_PER_ROW_ALIGNMENT; - let bytes_per_texel = conv::map_texture_format(src_texture.format, cmb.private_features) + let bytes_per_block = conv::map_texture_format(src_texture.format, cmb.private_features) .surface_desc() .bits as u32 / BITS_PER_BYTE; let dst_bytes_per_row = destination.layout.bytes_per_row; - if bytes_per_row_alignment % bytes_per_texel != 0 { + if bytes_per_row_alignment % bytes_per_block != 0 { return Err(TransferError::UnalignedBytesPerRow); } if dst_bytes_per_row % bytes_per_row_alignment != 0 { return Err(TransferError::UnalignedBytesPerRow); } - validate_texture_copy_range(source, src_texture.kind, copy_size)?; + validate_texture_copy_range(source, src_texture.format, src_texture.kind, copy_size)?; validate_linear_texture_data( &destination.layout, + src_texture.format, dst_buffer.size, - bytes_per_texel as BufferAddress, + bytes_per_block as BufferAddress, copy_size, )?; - let buffer_width = destination.layout.bytes_per_row / bytes_per_texel; + let (block_width, _) = conv::texture_block_size(src_texture.format); + + let buffer_width = (destination.layout.bytes_per_row / bytes_per_block) * block_width; let region = hal::command::BufferImageCopy { buffer_offset: destination.layout.offset, buffer_width, @@ -567,8 +583,8 @@ impl Global { } barriers.extend(dst_pending.map(|pending| pending.into_hal(dst_texture))); - validate_texture_copy_range(source, src_texture.kind, copy_size)?; - validate_texture_copy_range(destination, dst_texture.kind, copy_size)?; + validate_texture_copy_range(source, src_texture.format, src_texture.kind, copy_size)?; + validate_texture_copy_range(destination, dst_texture.format, dst_texture.kind, copy_size)?; let region = hal::command::ImageCopy { src_subresource: src_layers, diff --git a/wgpu-core/src/conv.rs b/wgpu-core/src/conv.rs index 2398601a16..310ec49bab 100644 --- a/wgpu-core/src/conv.rs +++ b/wgpu-core/src/conv.rs @@ -392,6 +392,141 @@ pub(crate) fn map_texture_format( H::D32SfloatS8Uint } } + + // BCn compressed formats + Tf::Bc1RgbaUnorm => H::Bc1RgbaUnorm, + Tf::Bc1RgbaUnormSrgb => H::Bc1RgbaSrgb, + Tf::Bc2RgbaUnorm => H::Bc2Unorm, + Tf::Bc2RgbaUnormSrgb => H::Bc2Srgb, + Tf::Bc3RgbaUnorm => H::Bc3Unorm, + Tf::Bc3RgbaUnormSrgb => H::Bc3Srgb, + Tf::Bc4RUnorm => H::Bc4Unorm, + Tf::Bc4RSnorm => H::Bc4Snorm, + Tf::Bc5RgUnorm => H::Bc5Unorm, + Tf::Bc5RgSnorm => H::Bc5Snorm, + Tf::Bc6hRgbSfloat => H::Bc6hSfloat, + Tf::Bc6hRgbUfloat => H::Bc6hUfloat, + Tf::Bc7RgbaUnorm => H::Bc7Unorm, + Tf::Bc7RgbaUnormSrgb => H::Bc7Srgb, + } +} + +pub fn texture_block_size(format: wgt::TextureFormat) -> (u32, u32) { + use wgt::TextureFormat as Tf; + match format { + Tf::R8Unorm + | Tf::R8Snorm + | Tf::R8Uint + | Tf::R8Sint + | Tf::R16Uint + | Tf::R16Sint + | Tf::R16Float + | Tf::Rg8Unorm + | Tf::Rg8Snorm + | Tf::Rg8Uint + | Tf::Rg8Sint + | Tf::R32Uint + | Tf::R32Sint + | Tf::R32Float + | Tf::Rg16Uint + | Tf::Rg16Sint + | Tf::Rg16Float + | Tf::Rgba8Unorm + | Tf::Rgba8UnormSrgb + | Tf::Rgba8Snorm + | Tf::Rgba8Uint + | Tf::Rgba8Sint + | Tf::Bgra8Unorm + | Tf::Bgra8UnormSrgb + | Tf::Rgb10a2Unorm + | Tf::Rg11b10Float + | Tf::Rg32Uint + | Tf::Rg32Sint + | Tf::Rg32Float + | Tf::Rgba16Uint + | Tf::Rgba16Sint + | Tf::Rgba16Float + | Tf::Rgba32Uint + | Tf::Rgba32Sint + | Tf::Rgba32Float => (1, 1), + + Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => { + unreachable!("unexpected depth format") + } + + Tf::Bc1RgbaUnorm + | Tf::Bc1RgbaUnormSrgb + | Tf::Bc2RgbaUnorm + | Tf::Bc2RgbaUnormSrgb + | Tf::Bc3RgbaUnorm + | Tf::Bc3RgbaUnormSrgb + | Tf::Bc4RUnorm + | Tf::Bc4RSnorm + | Tf::Bc5RgUnorm + | Tf::Bc5RgSnorm + | Tf::Bc6hRgbUfloat + | Tf::Bc6hRgbSfloat + | Tf::Bc7RgbaUnorm + | Tf::Bc7RgbaUnormSrgb => (4, 4), + } +} + +pub fn texture_features(format: wgt::TextureFormat) -> wgt::Features { + use wgt::TextureFormat as Tf; + match format { + Tf::R8Unorm + | Tf::R8Snorm + | Tf::R8Uint + | Tf::R8Sint + | Tf::R16Uint + | Tf::R16Sint + | Tf::R16Float + | Tf::Rg8Unorm + | Tf::Rg8Snorm + | Tf::Rg8Uint + | Tf::Rg8Sint + | Tf::R32Uint + | Tf::R32Sint + | Tf::R32Float + | Tf::Rg16Uint + | Tf::Rg16Sint + | Tf::Rg16Float + | Tf::Rgba8Unorm + | Tf::Rgba8UnormSrgb + | Tf::Rgba8Snorm + | Tf::Rgba8Uint + | Tf::Rgba8Sint + | Tf::Bgra8Unorm + | Tf::Bgra8UnormSrgb + | Tf::Rgb10a2Unorm + | Tf::Rg11b10Float + | Tf::Rg32Uint + | Tf::Rg32Sint + | Tf::Rg32Float + | Tf::Rgba16Uint + | Tf::Rgba16Sint + | Tf::Rgba16Float + | Tf::Rgba32Uint + | Tf::Rgba32Sint + | Tf::Rgba32Float + | Tf::Depth32Float + | Tf::Depth24Plus + | Tf::Depth24PlusStencil8 => wgt::Features::empty(), + + Tf::Bc1RgbaUnorm + | Tf::Bc1RgbaUnormSrgb + | Tf::Bc2RgbaUnorm + | Tf::Bc2RgbaUnormSrgb + | Tf::Bc3RgbaUnorm + | Tf::Bc3RgbaUnormSrgb + | Tf::Bc4RUnorm + | Tf::Bc4RSnorm + | Tf::Bc5RgUnorm + | Tf::Bc5RgSnorm + | Tf::Bc6hRgbUfloat + | Tf::Bc6hRgbSfloat + | Tf::Bc7RgbaUnorm + | Tf::Bc7RgbaUnormSrgb => wgt::Features::TEXTURE_COMPRESSION_BC, } } diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index db6477c299..87dd6a0c7e 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -948,6 +948,15 @@ impl Global { None => (), }; + let texture_features = conv::texture_features(desc.format); + if texture_features != wgt::Features::empty() && !device.features.contains(texture_features) + { + return Err(CreateTextureError::MissingFeature( + texture_features, + desc.format, + )); + } + device .trackers .lock() @@ -3088,6 +3097,8 @@ pub enum CreateTextureError { MAX_MIP_LEVELS )] InvalidMipLevelCount(u32), + #[error("Feature {0:?} must be enabled to create a texture of type {1:?}")] + MissingFeature(wgt::Features, TextureFormat), #[error(transparent)] HeapsError(#[from] gfx_memory::HeapsError), #[error("not enough memory left")] diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index d2e043db5a..581ca6785f 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -275,24 +275,32 @@ impl Global { } let texture_format = texture_guard[destination.texture].format; - let bytes_per_texel = conv::map_texture_format(texture_format, device.private_features) + let bytes_per_block = conv::map_texture_format(texture_format, device.private_features) .surface_desc() .bits as u32 / BITS_PER_BYTE; crate::command::validate_linear_texture_data( data_layout, + texture_format, data.len() as wgt::BufferAddress, - bytes_per_texel as wgt::BufferAddress, + bytes_per_block as wgt::BufferAddress, size, )?; + let (block_width, block_height) = conv::texture_block_size(texture_format); + let width_blocks = size.width / block_width; + let height_blocks = size.height / block_width; + + let texel_rows_per_image = data_layout.rows_per_image; + let block_rows_per_image = data_layout.rows_per_image / block_height; let bytes_per_row_alignment = get_lowest_common_denom( device.hal_limits.optimal_buffer_copy_pitch_alignment as u32, - bytes_per_texel, + bytes_per_block, ); - let stage_bytes_per_row = align_to(bytes_per_texel * size.width, bytes_per_row_alignment); - let stage_size = stage_bytes_per_row as u64 - * ((size.depth - 1) * data_layout.rows_per_image + size.height) as u64; + let stage_bytes_per_row = align_to(bytes_per_block * width_blocks, bytes_per_row_alignment); + + let block_rows_in_copy = (size.depth - 1) * block_rows_per_image + height_blocks; + let stage_size = stage_bytes_per_row as u64 * block_rows_in_copy as u64; let mut stage = device.prepare_stage(stage_size)?; { let mut mapped = stage @@ -312,8 +320,8 @@ impl Global { let copy_bytes_per_row = stage_bytes_per_row.min(data_layout.bytes_per_row) as usize; for layer in 0..size.depth { - let rows_offset = layer * data_layout.rows_per_image; - for row in 0..size.height { + let rows_offset = layer * block_rows_per_image; + for row in 0..height_blocks { let data_offset = (rows_offset + row) as usize * data_layout.bytes_per_row as usize; let stage_offset = @@ -333,14 +341,14 @@ impl Global { TextureUse::COPY_DST, ); check_texture_usage(dst.usage, wgt::TextureUsage::COPY_DST)?; - crate::command::validate_texture_copy_range(destination, dst.kind, size)?; + crate::command::validate_texture_copy_range(destination, dst.format, dst.kind, size)?; dst.life_guard.use_at(device.active_submission_index + 1); let region = hal::command::BufferImageCopy { buffer_offset: 0, - buffer_width: stage_bytes_per_row / bytes_per_texel, - buffer_height: data_layout.rows_per_image, + buffer_width: (stage_bytes_per_row / bytes_per_block) * block_width, + buffer_height: texel_rows_per_image, image_layers, image_offset, image_extent: conv::map_extent(size, dst.dimension), diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 4a351de451..b1c3bd8f54 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -131,6 +131,10 @@ impl Adapter { wgt::Features::DEPTH_CLAMPING, adapter_features.contains(hal::Features::DEPTH_CLAMP), ); + features.set( + wgt::Features::TEXTURE_COMPRESSION_BC, + adapter_features.contains(hal::Features::FORMAT_BC), + ); features.set( wgt::Features::SAMPLED_TEXTURE_BINDING_ARRAY, adapter_features.contains(hal::Features::TEXTURE_DESCRIPTOR_ARRAY), diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 7566499e2b..1bbf16cb9d 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -647,6 +647,32 @@ fn map_texture_format(format: wgt::TextureFormat) -> naga::TypeInner { Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => { panic!("Unexpected depth format") } + Tf::Bc1RgbaUnorm + | Tf::Bc1RgbaUnormSrgb + | Tf::Bc2RgbaUnorm + | Tf::Bc2RgbaUnormSrgb + | Tf::Bc3RgbaUnorm + | Tf::Bc3RgbaUnormSrgb + | Tf::Bc7RgbaUnorm + | Tf::Bc7RgbaUnormSrgb => Ti::Vector { + size: Vs::Quad, + kind: Sk::Float, + width: 8, + }, + Tf::Bc4RUnorm | Tf::Bc4RSnorm => Ti::Scalar { + kind: Sk::Float, + width: 8, + }, + Tf::Bc5RgUnorm | Tf::Bc5RgSnorm => Ti::Vector { + size: Vs::Bi, + kind: Sk::Float, + width: 8, + }, + Tf::Bc6hRgbUfloat | Tf::Bc6hRgbSfloat => Ti::Vector { + size: Vs::Tri, + kind: Sk::Float, + width: 8, + }, } } diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index c837387659..b79855965c 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -148,6 +148,17 @@ bitflags::bitflags! { /// /// This is a web and native feature. const DEPTH_CLAMPING = 0x0000_0000_0000_0001; + /// Enables BCn family of compressed textures. All BCn textures use 4x4 pixel blocks + /// with 8 or 16 bytes per block. + /// + /// Compressed textures sacrifice some quality in exchange for signifigantly reduced + /// bandwidth usage. + /// + /// Supported Platforms: + /// - desktops + /// + /// This is a web and native feature. + const TEXTURE_COMPRESSION_BC = 0x0000_0000_0000_0002; /// Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with /// COPY_DST and COPY_SRC respectively. This removes this requirement. /// @@ -634,7 +645,7 @@ pub enum TextureFormat { // Packed 32 bit formats /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. [0, 1023] ([0, 3] for alpha) converted to/from float [0, 1] in shader. Rgb10a2Unorm = 24, - /// Red, green, and blue channels. 11 bit float with no sign bit for RG channels. 10 bit float with no sign bti for blue channel. Float in shader. + /// Red, green, and blue channels. 11 bit float with no sign bit for RG channels. 10 bit float with no sign bit for blue channel. Float in shader. Rg11b10Float = 25, // Normal 64 bit formats @@ -666,6 +677,104 @@ pub enum TextureFormat { Depth24Plus = 36, /// Special depth/stencil format with at least 24 bit integer depth and 8 bits integer stencil. Depth24PlusStencil8 = 37, + + // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. + /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha. + /// [0, 64] ([0, 1] for alpha) converted to/from float [0, 1] in shader. + /// + /// Also known as DXT1. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc1RgbaUnorm = 38, + /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha. + /// Srgb-color [0, 64] ([0, 16] for alpha) converted to/from linear-color float [0, 1] in shader. + /// + /// Also known as DXT1. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc1RgbaUnormSrgb = 39, + /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha. + /// [0, 64] ([0, 16] for alpha) converted to/from float [0, 1] in shader. + /// + /// Also known as DXT3. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc2RgbaUnorm = 40, + /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha. + /// Srgb-color [0, 64] ([0, 256] for alpha) converted to/from linear-color float [0, 1] in shader. + /// + /// Also known as DXT3. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc2RgbaUnormSrgb = 41, + /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha. + /// [0, 64] ([0, 256] for alpha) converted to/from float [0, 1] in shader. + /// + /// Also known as DXT5. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc3RgbaUnorm = 42, + /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha. + /// Srgb-color [0, 64] ([0, 256] for alpha) converted to/from linear-color float [0, 1] in shader. + /// + /// Also known as DXT5. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc3RgbaUnormSrgb = 43, + /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R. + /// [0, 256] converted to/from float [0, 1] in shader. + /// + /// Also known as RGTC1. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc4RUnorm = 44, + /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R. + /// [-127, 127] converted to/from float [-1, 1] in shader. + /// + /// Also known as RGTC1. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc4RSnorm = 45, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG. + /// [0, 256] converted to/from float [0, 1] in shader. + /// + /// Also known as RGTC2. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc5RgUnorm = 46, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG. + /// [-127, 127] converted to/from float [-1, 1] in shader. + /// + /// Also known as RGTC2. + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc5RgSnorm = 47, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). Variable sized pallet. 16 bit unsigned float RGB. Float in shader. + /// + /// Also known as BPTC (float). + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc6hRgbUfloat = 48, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). Variable sized pallet. 16 bit signed float RGB. Float in shader. + /// + /// Also known as BPTC (float). + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc6hRgbSfloat = 49, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). Variable sized pallet. 8 bit integer RGBA. + /// [0, 256] converted to/from float [0, 1] in shader. + /// + /// Also known as BPTC (unorm). + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc7RgbaUnorm = 50, + /// 4x4 block compressed texture. 16 bytes per block (16 bit/px). Variable sized pallet. 8 bit integer RGBA. + /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader. + /// + /// Also known as BPTC (unorm). + /// + /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format. + Bc7RgbaUnormSrgb = 51, } bitflags::bitflags! { @@ -1743,7 +1852,21 @@ impl From for TextureComponentType { | TextureFormat::Rgb10a2Unorm | TextureFormat::Depth32Float | TextureFormat::Depth24Plus - | TextureFormat::Depth24PlusStencil8 => Self::Float, + | TextureFormat::Depth24PlusStencil8 + | TextureFormat::Bc1RgbaUnorm + | TextureFormat::Bc1RgbaUnormSrgb + | TextureFormat::Bc2RgbaUnorm + | TextureFormat::Bc2RgbaUnormSrgb + | TextureFormat::Bc3RgbaUnorm + | TextureFormat::Bc3RgbaUnormSrgb + | TextureFormat::Bc4RUnorm + | TextureFormat::Bc4RSnorm + | TextureFormat::Bc5RgUnorm + | TextureFormat::Bc5RgSnorm + | TextureFormat::Bc6hRgbSfloat + | TextureFormat::Bc6hRgbUfloat + | TextureFormat::Bc7RgbaUnorm + | TextureFormat::Bc7RgbaUnormSrgb => Self::Float, } } }