From ceb7ea1fab3852e74245c31226a7ec847a10eebe Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 18 Jul 2026 11:24:31 +0400 Subject: [PATCH] perf(assets): cache graph material validation --- crates/fparkan-assets/src/lib.rs | 33 +++++++++++++++++++++++++++++++- docs/tomes/05-render.md | 8 ++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/fparkan-assets/src/lib.rs b/crates/fparkan-assets/src/lib.rs index 31f4301..64853fd 100644 --- a/crates/fparkan-assets/src/lib.rs +++ b/crates/fparkan-assets/src/lib.rs @@ -1124,6 +1124,7 @@ pub fn extend_graph_report_with_visual_dependencies( .map_or(0, |value| value.saturating_add(1)); let mut diffuse_texture_validation = HashMap::new(); let mut lightmap_texture_validation = HashMap::new(); + let mut material_validation = HashMap::new(); for (prototype_index, prototype) in prototypes.iter().enumerate() { let PrototypeGeometry::Mesh(mesh) = &prototype.geometry else { @@ -1190,7 +1191,12 @@ pub fn extend_graph_report_with_visual_dependencies( ); continue; }; - match resolve_material(repository, &table, material_index) { + match resolve_material_validation_cached( + repository, + &table, + material_index, + &mut material_validation, + ) { Ok(material) => { report.material_resolved_count += 1; let material_key = ResourceKey { @@ -1900,6 +1906,31 @@ fn resolve_texm_validation_cached( result } +fn resolve_material_validation_cached( + repository: &R, + table: &WearTable, + index: u16, + cache: &mut HashMap, Result>, +) -> Result { + let request = table + .entries + .get(usize::from(index)) + .ok_or(MaterialError::WearIndexOutOfBounds { + index, + count: table.entries.len(), + }) + .map_err(|error| error.to_string())? + .material + .0 + .clone(); + if let Some(result) = cache.get(&request) { + return result.clone(); + } + let result = resolve_material(repository, table, index).map_err(|error| error.to_string()); + cache.insert(request, result.clone()); + result +} + #[cfg(test)] fn resolve_texture( repository: &R, diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md index 82e964d..a6e06a8 100644 --- a/docs/tomes/05-render.md +++ b/docs/tomes/05-render.md @@ -1063,6 +1063,14 @@ provenance while avoiding repeat format work for repeated components. The same demonstrate an additional checkpoint advance from this cache; it must not be reported as a measured startup improvement. +Visual-graph material resolution now also caches the complete success or failure +of each WEAR material request. Every material edge and failure remains in the +graph; the cache only avoids reopening and decoding an already resolved MAT0. +Under the controlled 60-second GOG first-root probe, the phase sequence advanced +from `GraphVisuals` to `AssetModelMeshes`, `AssetWearTables`, then +`AssetTextures` before termination. This is a bounded timing observation, not a +claim that a frame completed or that every run has identical timing. + `Assets` now has four ordered diagnostic sub-checkpoints: `AssetModelMeshes` (MSH), `AssetWearTables` (WEAR), `AssetMaterials` (MAT0) and `AssetTextures` (diffuse TEXM and lightmaps). The callback is observational: it neither changes