diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index 6970fc6d7..47a465bf0 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -910,9 +910,13 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type) return nullptr; // Check if asset has been already loaded - Asset* result = GetAsset(id); + Asset* result = nullptr; + AssetsLocker.Lock(); + Assets.TryGet(id, result); if (result) { + AssetsLocker.Unlock(); + // Validate type if (IsAssetTypeIdInvalid(type, result->GetTypeHandle()) && !result->Is(type)) { @@ -923,57 +927,39 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type) } // Check if that asset is during loading - AssetsLocker.Lock(); if (LoadCallAssets.Contains(id)) { AssetsLocker.Unlock(); // Wait for loading end by other thread - while (true) + bool contains = true; + while (contains) { Platform::Sleep(1); - result = nullptr; AssetsLocker.Lock(); - if (!LoadCallAssets.Contains(id)) - Assets.TryGet(id, result); + contains = LoadCallAssets.Contains(id); AssetsLocker.Unlock(); - if (result) - return result; } - } - else - { - // Mark asset as loading - LoadCallAssets.Add(id); - AssetsLocker.Unlock(); + Assets.TryGet(id, result); + return result; } - // Load asset - AssetInfo assetInfo; - result = load(id, type, assetInfo); - - // End loading - AssetsLocker.Lock(); - LoadCallAssets.Remove(id); + // Mark asset as loading and release lock so other threads can load other assets + LoadCallAssets.Add(id); AssetsLocker.Unlock(); - return result; -} - -Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& assetInfo) -{ // Get cached asset info (from registry) + AssetInfo assetInfo; if (!GetAssetInfo(id, assetInfo)) { LOG(Warning, "Invalid or missing asset ({0}, {1}).", id, type.ToString()); - return nullptr; + goto LOAD_FAILED; } - #if ASSETS_LOADING_EXTRA_VERIFICATION if (!FileSystem::FileExists(assetInfo.Path)) { LOG(Error, "Cannot find file '{0}'", assetInfo.Path); - return nullptr; + goto LOAD_FAILED; } #endif @@ -982,28 +968,27 @@ Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& if (factory == nullptr) { LOG(Error, "Cannot find asset factory. Info: {0}", assetInfo.ToString()); - return nullptr; + goto LOAD_FAILED; } // Create asset object - auto result = factory->New(assetInfo); + result = factory->New(assetInfo); if (result == nullptr) { LOG(Error, "Cannot create asset object. Info: {0}", assetInfo.ToString()); - return nullptr; + goto LOAD_FAILED; } - + ASSERT(result->GetID() == id); #if ASSETS_LOADING_EXTRA_VERIFICATION if (IsAssetTypeIdInvalid(type, result->GetTypeHandle()) && !result->Is(type)) { - LOG(Error, "Different loaded asset type! Asset: '{0}'. Expected type: {1}", assetInfo.ToString(), type.ToString()); + LOG(Warning, "Different loaded asset type! Asset: '{0}'. Expected type: {1}", assetInfo.ToString(), type.ToString()); result->DeleteObject(); - return nullptr; + goto LOAD_FAILED; } #endif // Register asset - ASSERT(result->GetID() == id); AssetsLocker.Lock(); #if ASSETS_LOADING_EXTRA_VERIFICATION ASSERT(!Assets.ContainsKey(id)); @@ -1011,12 +996,20 @@ Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& Assets.Add(id, result); // Start asset loading - // TODO: refactor this to create asset loading task-chain before AssetsLocker.Lock() to allow better parallelization result->startLoading(); + // Remove from the loading queue and release lock + LoadCallAssets.Remove(id); AssetsLocker.Unlock(); return result; + +LOAD_FAILED: + // Remove from loading queue + AssetsLocker.Lock(); + LoadCallAssets.Remove(id); + AssetsLocker.Unlock(); + return nullptr; } #if ENABLE_ASSETS_DISCOVERY diff --git a/Source/Engine/Content/Content.h b/Source/Engine/Content/Content.h index 6393ce48b..cce57194c 100644 --- a/Source/Engine/Content/Content.h +++ b/Source/Engine/Content/Content.h @@ -366,7 +366,6 @@ private: static void onAssetLoaded(Asset* asset); static void onAssetUnload(Asset* asset); static void onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId); - static Asset* load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& assetInfo); private: static void deleteFileSafety(const StringView& path, const Guid& id);