Optimize SkinnedModel::GetSkeletonMapping to not use locking for better perf when multi-threading

#3827
This commit is contained in:
Wojtek Figat
2026-02-07 00:46:32 +01:00
parent ecddb8aae5
commit ed5ad91a32
2 changed files with 22 additions and 13 deletions

View File

@@ -61,16 +61,24 @@ Array<String> SkinnedModel::GetBlendShapes()
SkinnedModel::SkeletonMapping SkinnedModel::GetSkeletonMapping(Asset* source, bool autoRetarget)
{
// Fast-path to use cached mapping
SkeletonMapping mapping;
mapping.TargetSkeleton = this;
SkeletonMappingData mappingData;
if (_skeletonMappingCache.TryGet(source, mappingData))
{
mapping.SourceSkeleton = mappingData.SourceSkeleton;
mapping.NodesMapping = mappingData.NodesMapping;
return mapping;
}
mapping.SourceSkeleton = nullptr;
if (WaitForLoaded() || !source || source->WaitForLoaded())
return mapping;
PROFILE_CPU();
ScopeLock lock(Locker);
SkeletonMappingData mappingData;
if (!_skeletonMappingCache.TryGet(source, mappingData))
{
PROFILE_CPU();
// Initialize the mapping
SkeletonRetarget* retarget = nullptr;
const Guid sourceId = source->GetID();
@@ -823,13 +831,13 @@ bool SkinnedModel::SaveMesh(WriteStream& stream, const ModelData& modelData, int
void SkinnedModel::ClearSkeletonMapping()
{
for (auto& e : _skeletonMappingCache)
for (const auto& e : _skeletonMappingCache)
{
e.Key->OnUnloaded.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
#if USE_EDITOR
e.Key->OnReloading.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
#endif
Allocator::Free(e.Value.NodesMapping.Get());
Allocator::Free((void*)e.Value.NodesMapping.Get());
}
_skeletonMappingCache.Clear();
}
@@ -837,8 +845,9 @@ void SkinnedModel::ClearSkeletonMapping()
void SkinnedModel::OnSkeletonMappingSourceAssetUnloaded(Asset* obj)
{
ScopeLock lock(Locker);
auto i = _skeletonMappingCache.Find(obj);
ASSERT(i != _skeletonMappingCache.End());
SkeletonMappingData mappingData;
bool found = _skeletonMappingCache.TryGet(obj, mappingData);
ASSERT(found);
// Unlink event
obj->OnUnloaded.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
@@ -847,8 +856,8 @@ void SkinnedModel::OnSkeletonMappingSourceAssetUnloaded(Asset* obj)
#endif
// Clear cache
Allocator::Free(i->Value.NodesMapping.Get());
_skeletonMappingCache.Remove(i);
Allocator::Free(mappingData.NodesMapping.Get());
_skeletonMappingCache.Remove(obj);
}
uint64 SkinnedModel::GetMemoryUsage() const