diff options
| author | Valentin Popov <valentin@popov.link> | 2026-07-18 10:24:31 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-07-18 10:24:31 +0300 |
| commit | ceb7ea1fab3852e74245c31226a7ec847a10eebe (patch) | |
| tree | 4f1155248e41472d8c074cb964562d707541860f | |
| parent | 421c9d7aa331a28063b5efc613ac178a0cc90f41 (diff) | |
| download | fparkan-ceb7ea1fab3852e74245c31226a7ec847a10eebe.tar.xz fparkan-ceb7ea1fab3852e74245c31226a7ec847a10eebe.zip | |
perf(assets): cache graph material validation
| -rw-r--r-- | crates/fparkan-assets/src/lib.rs | 33 | ||||
| -rw-r--r-- | docs/tomes/05-render.md | 8 |
2 files changed, 40 insertions, 1 deletions
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<R: ResourceRepository>( .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<R: ResourceRepository>( ); 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<R: ResourceRepository>( result } +fn resolve_material_validation_cached<R: ResourceRepository>( + repository: &R, + table: &WearTable, + index: u16, + cache: &mut HashMap<Vec<u8>, Result<ResolvedMaterial, String>>, +) -> Result<ResolvedMaterial, String> { + 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<R: ResourceRepository>( 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 |
