Skip to content

Commit

Permalink
Accelerate texture compression
Browse files Browse the repository at this point in the history
  • Loading branch information
hasenbanck committed Jan 8, 2025
1 parent 3558e9b commit 09baf26
Show file tree
Hide file tree
Showing 9 changed files with 297 additions and 151 deletions.
8 changes: 8 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Steam Hardware survey: https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam
[target.'cfg(target_arch="x86_64")']
rustflags = ["-C", "target-feature=+aes,+avx,+avx2,+cmpxchg16b,+fma,+sse3,+ssse3,+sse4.1,+sse4.2"]

# TODO: NHA create a new ticket in the Rust repo for this.
# On linux nighly Rust uses rust-lld, which runs into problems with linking C++ code.
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Zlinker-features=-lld"]
16 changes: 16 additions & 0 deletions 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 @@ -14,6 +14,7 @@ cpal = "0.15"
derive-new = "0.7"
encoding_rs = "0.8"
etherparse = "0.16"
fast_image_resize = "5.1"
fast-srgb8 = "1"
flate2 = { version = "1", default-features = false }
glidesort = "0.1"
Expand Down
5 changes: 4 additions & 1 deletion korangar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ chrono = { workspace = true }
cosmic-text = { workspace = true, features = ["std", "fontconfig"] }
derive-new = { workspace = true }
encoding_rs = { workspace = true }
fast_image_resize = { workspace = true, features = ["image", "rayon"], optional = true }
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 }
intel_tex_2 = { workspace = true, optional = true }
korangar_audio = { workspace = true }
korangar_debug = { workspace = true, optional = true }
korangar_interface = { workspace = true, features = ["serde", "cgmath"] }
Expand All @@ -43,8 +44,10 @@ wgpu = { workspace = true }
winit = { workspace = true }

[features]
default = ["texture_compression"]
debug = ["korangar_debug", "korangar_audio/debug", "ragnarok_packets/debug", "random_color"]
patched_as_folder = []
plain = ["korangar_debug/plain"]
unicode = ["korangar_debug/unicode"]
flac = ["korangar_audio/flac"]
texture_compression = ["fast_image_resize", "intel_tex_2"]
22 changes: 18 additions & 4 deletions korangar/src/graphics/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,30 @@ impl Display for ScreenSpaceAntiAliasing {
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum TextureCompression {
Off,
BC3,
BC7,
Bc3,
Bc7UltraFast,
Bc7VeryFast,
Bc7Fast,
Bc7Slow,
Bc7Slowest,
}

impl TextureCompression {
pub fn is_uncompressed(&self) -> bool {
*self == TextureCompression::Off
}
}

impl From<TextureCompression> for TextureFormat {
fn from(value: TextureCompression) -> Self {
match value {
TextureCompression::Off => TextureFormat::Rgba8UnormSrgb,
TextureCompression::BC3 => TextureFormat::Bc3RgbaUnormSrgb,
TextureCompression::BC7 => TextureFormat::Bc7RgbaUnormSrgb,
TextureCompression::Bc3 => TextureFormat::Bc3RgbaUnormSrgb,
TextureCompression::Bc7UltraFast
| TextureCompression::Bc7VeryFast
| TextureCompression::Bc7Fast
| TextureCompression::Bc7Slow
| TextureCompression::Bc7Slowest => TextureFormat::Bc7RgbaUnormSrgb,
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions korangar/src/interface/windows/settings/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,12 @@ where
PickList::default()
.with_options(vec![
("Off", TextureCompression::Off),
("BC3", TextureCompression::BC3),
("BC7", TextureCompression::BC7),
("Fastest", TextureCompression::Bc3),
("Ultra Fast", TextureCompression::Bc7UltraFast),
("Very Fast", TextureCompression::Bc7VeryFast),
("Fast", TextureCompression::Bc7Fast),
("Slow", TextureCompression::Bc7Slow),
("Slowest", TextureCompression::Bc7Slowest),
])
.with_selected(self.texture_compression.clone())
.with_event(Box::new(Vec::new))
Expand Down
42 changes: 32 additions & 10 deletions korangar/src/loaders/async/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::cmp::PartialEq;
use std::num::NonZero;
use std::sync::{Arc, Mutex};

use hashbrown::HashMap;
Expand Down Expand Up @@ -55,6 +56,12 @@ impl PartialEq for LoadStatus {
}
}

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
enum TaskType {
Light,
Heavy,
}

pub struct AsyncLoader {
action_loader: Arc<ActionLoader>,
animation_loader: Arc<AnimationLoader>,
Expand All @@ -63,7 +70,8 @@ pub struct AsyncLoader {
sprite_loader: Arc<SpriteLoader>,
texture_loader: Arc<TextureLoader>,
pending_loads: Arc<Mutex<HashMap<LoaderId, LoadStatus>>>,
thread_pool: ThreadPool,
light_task_thread_pool: ThreadPool,
heavy_task_thread_pool: ThreadPool,
}

impl AsyncLoader {
Expand All @@ -75,9 +83,17 @@ impl AsyncLoader {
sprite_loader: Arc<SpriteLoader>,
texture_loader: Arc<TextureLoader>,
) -> Self {
let thread_pool = ThreadPoolBuilder::new()
.num_threads(2)
.thread_name(|_| "async loader".to_string())
let parallelism = std::thread::available_parallelism().unwrap_or_else(|_| NonZero::new(2).unwrap());

let light_task_thread_pool = ThreadPoolBuilder::new()
.num_threads(1)
.thread_name(|number| format!("light task thread pool {number}"))
.build()
.unwrap();

let heavy_task_thread_pool = ThreadPoolBuilder::new()
.num_threads(parallelism.get())
.thread_name(|number| format!("heavy task thread pool {number}"))
.build()
.unwrap();

Expand All @@ -89,7 +105,8 @@ impl AsyncLoader {
sprite_loader,
texture_loader,
pending_loads: Arc::new(Mutex::new(HashMap::new())),
thread_pool,
light_task_thread_pool,
heavy_task_thread_pool,
}
}

Expand All @@ -107,7 +124,7 @@ impl AsyncLoader {
let action_loader = self.action_loader.clone();
let animation_loader = self.animation_loader.clone();

self.request_load(LoaderId::AnimationData(entity_id), move || {
self.request_load(TaskType::Light, LoaderId::AnimationData(entity_id), move || {
#[cfg(feature = "debug")]
let _load_measurement = Profiler::start_measurement("animation data load");

Expand Down Expand Up @@ -137,7 +154,7 @@ impl AsyncLoader {
let texture_loader = self.texture_loader.clone();
let path = path.to_string();

self.request_load(LoaderId::ItemSprite(item_id), move || {
self.request_load(TaskType::Light, LoaderId::ItemSprite(item_id), move || {
#[cfg(feature = "debug")]
let _load_measurement = Profiler::start_measurement("item sprite load");

Expand Down Expand Up @@ -167,7 +184,7 @@ impl AsyncLoader {
let model_loader = self.model_loader.clone();
let texture_loader = self.texture_loader.clone();

self.request_load(LoaderId::Map(map_name.clone()), move || {
self.request_load(TaskType::Heavy, LoaderId::Map(map_name.clone()), move || {
#[cfg(feature = "debug")]
let _load_measurement = Profiler::start_measurement("map load");

Expand All @@ -183,15 +200,20 @@ impl AsyncLoader {
});
}

fn request_load<F>(&self, id: LoaderId, load_function: F)
fn request_load<F>(&self, task_type: TaskType, id: LoaderId, load_function: F)
where
F: FnOnce() -> Result<LoadableResource, LoadError> + Send + 'static,
{
let pending_loads = Arc::clone(&self.pending_loads);

pending_loads.lock().unwrap().insert(id.clone(), LoadStatus::Loading);

self.thread_pool.spawn(move || {
let thread_pool = match task_type {
TaskType::Light => &self.light_task_thread_pool,
TaskType::Heavy => &self.heavy_task_thread_pool,
};

thread_pool.spawn(move || {
#[cfg(feature = "debug")]
let _measurement = threads::Loader::start_frame();

Expand Down
Loading

0 comments on commit 09baf26

Please sign in to comment.