Skip to content

Commit

Permalink
Implement BC texture compression
Browse files Browse the repository at this point in the history
  • Loading branch information
hasenbanck committed Jan 7, 2025
1 parent 96b0e5c commit 3558e9b
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 230 deletions.
38 changes: 37 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ flate2 = { version = "1", default-features = false }
glidesort = "0.1"
hashbrown = "0.15"
image = { version = "0.25", default-features = false }
intel_tex_2 = "0.4"
kira = { version = "0.9", default-features = false }
korangar_audio = { path = "korangar_audio" }
korangar_debug = { path = "korangar_debug" }
Expand Down
1 change: 1 addition & 0 deletions korangar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ flate2 = { workspace = true, features = ["zlib-rs"] }
hashbrown = { workspace = true }
glidesort = { workspace = true }
image = { workspace = true, features = ["bmp", "jpeg", "png", "tga", "rayon"] }
intel_tex_2 = { workspace = true }
korangar_audio = { workspace = true }
korangar_debug = { workspace = true, optional = true }
korangar_interface = { workspace = true, features = ["serde", "cgmath"] }
Expand Down
13 changes: 13 additions & 0 deletions korangar/src/graphics/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct Capabilities {
bindless: bool,
multidraw_indirect: bool,
clamp_to_border: bool,
texture_compression: bool,
#[cfg(feature = "debug")]
polygon_mode_line: bool,
required_features: Features,
Expand All @@ -37,6 +38,7 @@ impl Capabilities {
bindless: false,
multidraw_indirect: false,
clamp_to_border: false,
texture_compression: false,
#[cfg(feature = "debug")]
polygon_mode_line: false,
required_features: Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
Expand All @@ -58,6 +60,7 @@ impl Capabilities {
adapter_features,
Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
);
Self::check_feature(adapter_features, Features::TEXTURE_COMPRESSION_BC);
Self::check_feature(adapter_features, Features::TEXTURE_BINDING_ARRAY);
Self::check_feature(adapter_features, Features::POLYGON_MODE_LINE);
}
Expand Down Expand Up @@ -85,6 +88,11 @@ impl Capabilities {
capabilities.required_features |= Features::ADDRESS_MODE_CLAMP_TO_BORDER | Features::ADDRESS_MODE_CLAMP_TO_ZERO;
}

if adapter_features.contains(Features::TEXTURE_COMPRESSION_BC) {
capabilities.texture_compression = true;
capabilities.required_features |= Features::TEXTURE_COMPRESSION_BC;
}

#[cfg(feature = "debug")]
if adapter_features.contains(Features::POLYGON_MODE_LINE) {
capabilities.polygon_mode_line = true;
Expand Down Expand Up @@ -135,6 +143,11 @@ impl Capabilities {
self.clamp_to_border
}

/// Returns `true` if the backend supports BC texture compression.
pub fn supports_texture_compression(&self) -> bool {
self.texture_compression
}

/// Returns `true` if the backend allows drawing triangles as lines
/// (wireframe) instead of filled.
#[cfg(feature = "debug")]
Expand Down
11 changes: 10 additions & 1 deletion korangar/src/graphics/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use winit::window::Window;

use super::{
AntiAliasingResource, Capabilities, EntityInstruction, FramePacer, FrameStage, GlobalContext, LimitFramerate, ModelInstruction, Msaa,
Prepare, PresentModeInfo, ScreenSpaceAntiAliasing, ShadowDetail, Ssaa, Surface, TextureSamplerType, RENDER_TO_TEXTURE_FORMAT,
Prepare, PresentModeInfo, ScreenSpaceAntiAliasing, ShadowDetail, Ssaa, Surface, TextureCompression, TextureSamplerType,
RENDER_TO_TEXTURE_FORMAT,
};
use crate::graphics::instruction::RenderInstruction;
use crate::graphics::passes::*;
Expand Down Expand Up @@ -428,6 +429,14 @@ impl GraphicsEngine {
ssaa
}

pub fn check_texture_compression_requirements(&self, texture_compression: TextureCompression) -> TextureCompression {
if self.capabilities.supports_texture_compression() {
texture_compression
} else {
TextureCompression::Off
}
}

pub fn on_suspended(&mut self) {
// Android devices are expected to drop their surface view.
if cfg!(target_os = "android") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn vs_main(
fn fs_main(input: VertexOutput) -> @location(0) vec4<f32> {
var diffuse_color = textureSampleLevel(texture, texture_sampler, input.texture_coordinates, 0.0);

if (diffuse_color.a < 1.0) {
if (diffuse_color.a == 0.0) {
discard;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn fs_main(input: VertexOutput) -> @builtin(frag_depth) f32 {

let light_distance = length(input.world_position.xyz - pass_uniforms.light_position.xyz);

if (diffuse_color.a != 1.0) {
if (diffuse_color.a == 0.0) {
discard;
}

Expand Down
18 changes: 18 additions & 0 deletions korangar/src/graphics/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::num::NonZeroU32;
#[cfg(feature = "debug")]
use derive_new::new;
use serde::{Deserialize, Serialize};
use wgpu::TextureFormat;

use crate::interface::layout::ScreenSize;

Expand Down Expand Up @@ -160,6 +161,23 @@ impl Display for ScreenSpaceAntiAliasing {
}
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum TextureCompression {
Off,
BC3,
BC7,
}

impl From<TextureCompression> for TextureFormat {
fn from(value: TextureCompression) -> Self {
match value {
TextureCompression::Off => TextureFormat::Rgba8UnormSrgb,
TextureCompression::BC3 => TextureFormat::Bc3RgbaUnormSrgb,
TextureCompression::BC7 => TextureFormat::Bc7RgbaUnormSrgb,
}
}
}

#[cfg(feature = "debug")]
#[derive(Copy, Clone, Default, new)]
pub struct RenderSettings {
Expand Down
62 changes: 46 additions & 16 deletions korangar/src/graphics/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use hashbrown::HashMap;
use korangar_util::container::Cacheable;
use wgpu::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource,
BindingType, Device, Extent3d, ImageDataLayout, Queue, ShaderStages, TextureAspect, TextureDescriptor, TextureDimension, TextureFormat,
TextureSampleType, TextureUsages, TextureView, TextureViewDescriptor, TextureViewDimension,
BindingType, Device, Extent3d, ImageCopyTexture, ImageDataLayout, Origin3d, Queue, ShaderStages, TextureAspect, TextureDescriptor,
TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureView, TextureViewDescriptor, TextureViewDimension,
};

use crate::interface::layout::ScreenSize;
Expand Down Expand Up @@ -73,24 +73,54 @@ impl Texture {
}
}

/// This function doesn't upload mip-map data. Mip maps should be written
/// using the `MipMapRenderPassContext` & `Lanczos3Drawer`.
pub fn new_with_data(device: &Device, queue: &Queue, descriptor: &TextureDescriptor, image_data: &[u8], transparent: bool) -> Self {
let id = TEXTURE_ID.fetch_add(1, Ordering::Relaxed);
let label = descriptor.label.map(|label| label.to_string());
let texture = device.create_texture(descriptor);
let block_size = texture.format().block_copy_size(None).unwrap();

queue.write_texture(
texture.as_image_copy(),
image_data,
ImageDataLayout {
offset: 0,
bytes_per_row: Some(descriptor.size.width * block_size),
rows_per_image: Some(descriptor.size.height),
},
descriptor.size,
);
let format = texture.format();

let (block_width, block_height) = format.block_dimensions();
let block_size = format.block_copy_size(None).unwrap();

let mut offset = 0;
let mut mip_width = descriptor.size.width;
let mut mip_height = descriptor.size.height;

for mip_level in 0..descriptor.mip_level_count {
let width_blocks = mip_width.div_ceil(block_width);
let height_blocks = mip_height.div_ceil(block_height);

let bytes_per_row = width_blocks * block_size;
let mip_size = bytes_per_row * height_blocks;

if offset + mip_size as usize <= image_data.len() {
queue.write_texture(
ImageCopyTexture {
texture: &texture,
mip_level,
origin: Origin3d::ZERO,
aspect: TextureAspect::All,
},
&image_data[offset..offset + mip_size as usize],
ImageDataLayout {
offset: 0,
bytes_per_row: Some(bytes_per_row),
rows_per_image: None,
},
Extent3d {
width: mip_width,
height: mip_height,
depth_or_array_layers: 1,
},
);

offset += mip_size as usize;
mip_width = (mip_width / 2).max(1);
mip_height = (mip_height / 2).max(1);
} else {
break;
}
}

let texture_view = texture.create_view(&TextureViewDescriptor {
label: descriptor.label,
Expand Down
Loading

0 comments on commit 3558e9b

Please sign in to comment.