From 2e14b1d5dd99ecd577c96ea4aaacdd584872a338 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 18 Jul 2026 13:17:06 +0400 Subject: perf(assets): cache visual wear validation --- crates/fparkan-assets/src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'crates/fparkan-assets') diff --git a/crates/fparkan-assets/src/lib.rs b/crates/fparkan-assets/src/lib.rs index d133574..11e324f 100644 --- a/crates/fparkan-assets/src/lib.rs +++ b/crates/fparkan-assets/src/lib.rs @@ -50,6 +50,9 @@ const TEXTURES_ARCHIVE: &str = "textures.lib"; const LIGHTMAP_ARCHIVE: &str = "lightmap.lib"; const VISUAL_DEPENDENCY_PROGRESS_INTERVAL: usize = 64; +type WearValidationCache = + HashMap<(NormalizedPath, Vec), Result>; + /// Canonical terrain archive paths derived from a mission land reference. #[derive(Clone, Debug, Eq, PartialEq)] pub struct MissionTerrainPaths { @@ -1202,6 +1205,7 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress { report.wear_resolved_count += 1; let wear_key = match wear_resource_key(mesh) { @@ -1457,7 +1461,7 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress( decode_wear(&bytes).map_err(AssetError::Material) } +fn resolve_wear_table_cached( + repository: &R, + mesh: &ResourceKey, + cache: &mut WearValidationCache, +) -> Result { + let wear_key = wear_resource_key(mesh).map_err(|error| error.to_string())?; + let cache_key = (wear_key.archive.clone(), wear_key.name.0.clone()); + if let Some(result) = cache.get(&cache_key) { + return result.clone(); + } + let result = resolve_wear_table(repository, mesh).map_err(|error| error.to_string()); + cache.insert(cache_key, result.clone()); + result +} + fn push_visual_failure( report: &mut PrototypeGraphReport, graph: &PrototypeGraph, @@ -2323,6 +2342,26 @@ mod tests { ); } + #[test] + fn wear_validation_cache_replays_archive_qualified_failure() { + let repository = repository_with_archives(&[]); + let mesh = ResourceKey { + archive: parse_path("static.rlb").expect("archive"), + name: resource_name(b"tree.msh"), + type_id: Some(0x4853_454D), + }; + let mut cache = WearValidationCache::new(); + cache.insert( + (mesh.archive.clone(), b"tree.wea".to_vec()), + Err("cached WEAR failure".to_string()), + ); + + assert_eq!( + resolve_wear_table_cached(&repository, &mesh, &mut cache), + Err("cached WEAR failure".to_string()) + ); + } + #[test] fn count_only_plan_uses_graph_requests() { let graph = PrototypeGraph::default(); -- cgit v1.2.3