perf(assets): cache visual wear validation

This commit is contained in:
2026-07-18 13:17:06 +04:00
parent 67308d4019
commit 2e14b1d5dd
2 changed files with 52 additions and 2 deletions
+41 -2
View File
@@ -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<u8>), Result<fparkan_material::WearTable, String>>;
/// 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<R: ResourceRep
let mut diffuse_texture_validation = HashMap::new();
let mut lightmap_texture_validation = HashMap::new();
let mut material_validation = HashMap::new();
let mut wear_validation = HashMap::new();
let mut wear_requests = 0usize;
let mut material_requests = 0usize;
let mut texture_requests = 0usize;
@@ -1236,7 +1240,7 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress<R: ResourceRep
VisualDependencyPhase::Wear,
wear_requests,
);
match resolve_wear_table(repository, mesh) {
match resolve_wear_table_cached(repository, mesh, &mut wear_validation) {
Ok(table) => {
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<R: ResourceRep
mesh.name.0.clone(),
PrototypeGraphEdge::MeshToWear,
PrototypeGraphRequiredness::Required,
&message.to_string(),
&message,
),
}
}
@@ -1899,6 +1903,21 @@ fn resolve_wear_table<R: ResourceRepository>(
decode_wear(&bytes).map_err(AssetError::Material)
}
fn resolve_wear_table_cached<R: ResourceRepository>(
repository: &R,
mesh: &ResourceKey,
cache: &mut WearValidationCache,
) -> Result<fparkan_material::WearTable, String> {
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();
+11
View File
@@ -1151,6 +1151,17 @@ the measured unfinished interval for this run. It still does not allocate that
time among MAT0 decode, graph allocation, archive I/O, OS cache state, or the
interleaved TEXM requests.
Visual expansion now also caches WEAR validation by the complete derived WEAR
archive/name key and replays both successes and failures. It still creates each
per-prototype WEAR edge, increments the same request counters, and reports the
same failure provenance. A unit test verifies an archive-qualified cached
failure is replayed without consulting the repository. In a matched bounded
Part 2 probe the first TEXM-64 marker occurred at 135,520 ms, versus 134,793
ms in the preceding sample, and neither run reached `Assets`; therefore this
corpus does not evidence a startup advance from WEAR caching. The path is kept
as a correctness-preserving duplicate-resolve optimization, not a causal
performance claim.
A rebuilt executable then ran a controlled 180-second Part 2 `Autodemo.00`
probe with the append-only trace. Before exact-child termination it recorded
`GraphVisualTextureRequests(64)`, `GraphVisualMaterialRequests(100)`, and every