perf(assets): cache prepared model dependencies
This commit is contained in:
@@ -1430,6 +1430,8 @@ struct PreparedVisualBundle {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PreparationCache {
|
struct PreparationCache {
|
||||||
|
models: Vec<(ResourceKey, ModelAsset)>,
|
||||||
|
wears: Vec<(ResourceKey, WearTable)>,
|
||||||
diffuse: HashMap<Vec<u8>, PreparedTexture>,
|
diffuse: HashMap<Vec<u8>, PreparedTexture>,
|
||||||
lightmaps: HashMap<Vec<u8>, PreparedTexture>,
|
lightmaps: HashMap<Vec<u8>, PreparedTexture>,
|
||||||
materials: HashMap<Vec<u8>, ResolvedMaterial>,
|
materials: HashMap<Vec<u8>, ResolvedMaterial>,
|
||||||
@@ -1453,13 +1455,7 @@ fn prepare_visual_with_repository_internal<R: ResourceRepository>(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let nres = decode_nres(
|
let model = prepare_model_cached(repository, mesh_key, preparation_cache)?;
|
||||||
read_key(repository, mesh_key, Some("mesh"))?,
|
|
||||||
ReadProfile::Compatible,
|
|
||||||
)
|
|
||||||
.map_err(AssetError::Nres)?;
|
|
||||||
let msh_document = decode_msh(&nres).map_err(AssetError::Msh)?;
|
|
||||||
let model = validate_msh(&msh_document).map_err(AssetError::Msh)?;
|
|
||||||
let model_id = AssetId::new((identity_policy.model)(proto));
|
let model_id = AssetId::new((identity_policy.model)(proto));
|
||||||
let prepared_model = PreparedModel {
|
let prepared_model = PreparedModel {
|
||||||
id: model_id,
|
id: model_id,
|
||||||
@@ -1474,8 +1470,7 @@ fn prepare_visual_with_repository_internal<R: ResourceRepository>(
|
|||||||
name: wear_name,
|
name: wear_name,
|
||||||
type_id: Some(WEAR_KIND),
|
type_id: Some(WEAR_KIND),
|
||||||
};
|
};
|
||||||
let wear = decode_wear(&read_key(repository, &wear_key, Some("wear"))?)
|
let wear = prepare_wear_cached(repository, &wear_key, preparation_cache)?;
|
||||||
.map_err(AssetError::Material)?;
|
|
||||||
let wear_id = AssetId::new((identity_policy.wear)(proto));
|
let wear_id = AssetId::new((identity_policy.wear)(proto));
|
||||||
let prepared_wear = PreparedWear {
|
let prepared_wear = PreparedWear {
|
||||||
id: wear_id,
|
id: wear_id,
|
||||||
@@ -1593,6 +1588,43 @@ fn read_key<R: ResourceRepository>(
|
|||||||
Ok(Arc::from(bytes.into_owned()))
|
Ok(Arc::from(bytes.into_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_model_cached<R: ResourceRepository>(
|
||||||
|
repository: &R,
|
||||||
|
key: &ResourceKey,
|
||||||
|
cache: &mut PreparationCache,
|
||||||
|
) -> Result<ModelAsset, AssetError> {
|
||||||
|
if let Some((_, model)) = cache
|
||||||
|
.models
|
||||||
|
.iter()
|
||||||
|
.find(|(cached_key, _)| cached_key == key)
|
||||||
|
{
|
||||||
|
return Ok(model.clone());
|
||||||
|
}
|
||||||
|
let nres = decode_nres(
|
||||||
|
read_key(repository, key, Some("mesh"))?,
|
||||||
|
ReadProfile::Compatible,
|
||||||
|
)
|
||||||
|
.map_err(AssetError::Nres)?;
|
||||||
|
let document = decode_msh(&nres).map_err(AssetError::Msh)?;
|
||||||
|
let model = validate_msh(&document).map_err(AssetError::Msh)?;
|
||||||
|
cache.models.push((key.clone(), model.clone()));
|
||||||
|
Ok(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_wear_cached<R: ResourceRepository>(
|
||||||
|
repository: &R,
|
||||||
|
key: &ResourceKey,
|
||||||
|
cache: &mut PreparationCache,
|
||||||
|
) -> Result<WearTable, AssetError> {
|
||||||
|
if let Some((_, wear)) = cache.wears.iter().find(|(cached_key, _)| cached_key == key) {
|
||||||
|
return Ok(wear.clone());
|
||||||
|
}
|
||||||
|
let wear =
|
||||||
|
decode_wear(&read_key(repository, key, Some("wear"))?).map_err(AssetError::Material)?;
|
||||||
|
cache.wears.push((key.clone(), wear.clone()));
|
||||||
|
Ok(wear)
|
||||||
|
}
|
||||||
|
|
||||||
fn map_resource_error(label: &str, key: &ResourceKey, source: ResourceError) -> AssetError {
|
fn map_resource_error(label: &str, key: &ResourceKey, source: ResourceError) -> AssetError {
|
||||||
AssetError::Resource {
|
AssetError::Resource {
|
||||||
context: format!(
|
context: format!(
|
||||||
|
|||||||
@@ -1056,6 +1056,13 @@ last checkpoint advanced to `Assets`. The process was deliberately terminated
|
|||||||
before a frame, so this proves reduced visual-graph work rather than a Vulkan
|
before a frame, so this proves reduced visual-graph work rather than a Vulkan
|
||||||
acceptance result.
|
acceptance result.
|
||||||
|
|
||||||
|
Asset preparation additionally caches validated MSH models and decoded WEAR
|
||||||
|
tables by their complete resource key. This preserves separate prepared visual
|
||||||
|
provenance while avoiding repeat format work for repeated components. The same
|
||||||
|
60-second first-root GOG probe remained at `Assets`, so that corpus does not
|
||||||
|
demonstrate an additional checkpoint advance from this cache; it must not be
|
||||||
|
reported as a measured startup improvement.
|
||||||
|
|
||||||
The same source-axis proof now applies to `TerrainWorld`: its `Land.msh` surface
|
The same source-axis proof now applies to `TerrainWorld`: its `Land.msh` surface
|
||||||
height query and `Land.map` areal/grid lookup use XY ground coordinates, return
|
height query and `Land.map` areal/grid lookup use XY ground coordinates, return
|
||||||
source Z height, and leave raycasts as full 3D intersections. The Part 1 and
|
source Z height, and leave raycasts as full 3D intersections. The Part 1 and
|
||||||
|
|||||||
Reference in New Issue
Block a user