Fix binary asset dependencies tracking when dependent asset gets loaded later on
#3951 Adds additional cache for dependencies tracking to update them when other asset gets loaded later on. Remove critical-section from `LoadAssetTask` that was causing some deadlocks (data access is already atomic there).
This commit is contained in:
@@ -84,6 +84,11 @@ bool BinaryAsset::Init(AssetInitData& initData)
|
||||
{
|
||||
asset->_dependantAssets.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dependency is not yet loaded to keep track this link to act when it's loaded
|
||||
Content::onAssetDepend(this, e.First);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API BinaryAsset : public Asset
|
||||
{
|
||||
DECLARE_ASSET_HEADER(BinaryAsset);
|
||||
friend Content;
|
||||
protected:
|
||||
AssetHeader _header;
|
||||
FlaxStorageReference _storageRef; // Allow asset to have missing storage reference but only before asset is loaded or if it's virtual
|
||||
|
||||
@@ -94,6 +94,9 @@ namespace
|
||||
DateTime LastWorkspaceDiscovery;
|
||||
CriticalSection WorkspaceDiscoveryLocker;
|
||||
#endif
|
||||
#if USE_EDITOR
|
||||
Dictionary<Guid, HashSet<BinaryAsset*>> PendingDependencies;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_ASSETS_DISCOVERY
|
||||
@@ -157,6 +160,9 @@ void ContentService::Update()
|
||||
{
|
||||
auto asset = LoadedAssetsToInvoke.Dequeue();
|
||||
asset->onLoaded_MainThread();
|
||||
#if USE_EDITOR
|
||||
Content::onAddDependencies(asset);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1027,10 +1033,17 @@ bool Content::CloneAssetFile(const StringView& dstPath, const StringView& srcPat
|
||||
FileSystem::DeleteFile(tmpPath);
|
||||
|
||||
// Reload storage
|
||||
if (auto storage = ContentStorageManager::GetStorage(dstPath, false))
|
||||
auto storage = ContentStorageManager::GetStorage(dstPath, false);
|
||||
if (storage && storage->IsLoaded())
|
||||
{
|
||||
storage->Reload();
|
||||
}
|
||||
else if (auto dependencies = PendingDependencies.TryGet(dstId))
|
||||
{
|
||||
// Destination storage is not loaded but there are other assets that depend on it so update them
|
||||
for (const auto& e : *dependencies)
|
||||
e.Item->OnDependencyModified(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1218,6 +1231,9 @@ void Content::tryCallOnLoaded(Asset* asset)
|
||||
{
|
||||
LoadedAssetsToInvoke.RemoveAtKeepOrder(index);
|
||||
asset->onLoaded_MainThread();
|
||||
#if USE_EDITOR
|
||||
onAddDependencies(asset);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1235,6 +1251,10 @@ void Content::onAssetUnload(Asset* asset)
|
||||
Assets.Remove(asset->GetID());
|
||||
UnloadQueue.Remove(asset);
|
||||
LoadedAssetsToInvoke.Remove(asset);
|
||||
#if USE_EDITOR
|
||||
for (auto& e : PendingDependencies)
|
||||
e.Value.Remove(asset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Content::onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId)
|
||||
@@ -1242,8 +1262,42 @@ void Content::onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId
|
||||
ScopeLock locker(AssetsLocker);
|
||||
Assets.Remove(oldId);
|
||||
Assets.Add(newId, asset);
|
||||
#if USE_EDITOR
|
||||
if (PendingDependencies.ContainsKey(oldId))
|
||||
{
|
||||
auto deps = MoveTemp(PendingDependencies[oldId]);
|
||||
PendingDependencies.Remove(oldId);
|
||||
PendingDependencies.Add(newId, MoveTemp(deps));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void Content::onAssetDepend(BinaryAsset* asset, const Guid& otherId)
|
||||
{
|
||||
ScopeLock locker(AssetsLocker);
|
||||
PendingDependencies[otherId].Add(asset);
|
||||
}
|
||||
|
||||
void Content::onAddDependencies(Asset* asset)
|
||||
{
|
||||
auto it = PendingDependencies.Find(asset->GetID());
|
||||
if (it.IsNotEnd())
|
||||
{
|
||||
auto& dependencies = it->Value;
|
||||
auto binaryAsset = Asset::Cast<BinaryAsset>(asset);
|
||||
if (binaryAsset)
|
||||
{
|
||||
for (const auto& e : dependencies)
|
||||
binaryAsset->_dependantAssets.Add(e.Item);
|
||||
}
|
||||
PendingDependencies.Remove(it);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool Content::IsAssetTypeIdInvalid(const ScriptingTypeHandle& type, const ScriptingTypeHandle& assetType)
|
||||
{
|
||||
// Skip if no restrictions for the type
|
||||
|
||||
@@ -389,6 +389,12 @@ private:
|
||||
static void onAssetLoaded(Asset* asset);
|
||||
static void onAssetUnload(Asset* asset);
|
||||
static void onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId);
|
||||
#if USE_EDITOR
|
||||
friend class BinaryAsset;
|
||||
friend class ContentService;
|
||||
static void onAssetDepend(BinaryAsset* asset, const Guid& otherId);
|
||||
static void onAddDependencies(Asset* asset);
|
||||
#endif
|
||||
static void deleteFileSafety(const StringView& path, const Guid& id);
|
||||
|
||||
// Internal bindings
|
||||
|
||||
@@ -80,7 +80,6 @@ private:
|
||||
auto asset = Asset.Get();
|
||||
if (asset)
|
||||
{
|
||||
asset->Locker.Lock();
|
||||
Task* task = (Task*)Platform::AtomicRead(&asset->_loadingTask);
|
||||
if (task)
|
||||
{
|
||||
@@ -99,7 +98,6 @@ private:
|
||||
task = task->GetContinueWithTask();
|
||||
} while (task);
|
||||
}
|
||||
asset->Locker.Unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user