Browse Source

Refactored resource loading so it will load dependencies even if the parent resource is already loaded (This probably broke async resource loading in some way)

BearishSun 10 years ago
parent
commit
00b3967714
2 changed files with 91 additions and 23 deletions
  1. 91 22
      BansheeCore/Source/BsResources.cpp
  2. 0 1
      MBansheeEditor/EditorApplication.cs

+ 91 - 22
BansheeCore/Source/BsResources.cpp

@@ -180,6 +180,64 @@ namespace BansheeEngine
 				}
 			}
 		}
+		else if (loadDependencies && savedResourceData != nullptr) // Queue dependencies in case they aren't already loaded
+		{
+			const Vector<String>& dependencies = savedResourceData->getDependencies();
+			if (!dependencies.empty())
+			{
+				{
+					BS_LOCK_MUTEX(mInProgressResourcesMutex);
+
+					ResourceLoadData* loadData = nullptr;
+
+					auto iterFind = mInProgressResources.find(UUID);
+					if (iterFind == mInProgressResources.end()) // Fully loaded
+					{
+						loadData = bs_new<ResourceLoadData>(outputResource, 0);
+						loadData->resource = outputResource;
+						loadData->remainingDependencies = 0;
+						loadData->notifyImmediately = synchronous; // Make resource listener trigger before exit if loading synchronously
+
+						mInProgressResources[UUID] = loadData;
+					}
+					else
+					{
+						loadData = iterFind->second;
+					}
+
+					// Register dependencies and count them so we know when the resource is fully loaded
+					for (auto& dependency : dependencies)
+					{
+						if (dependency != UUID)
+						{
+							bool registerDependency = true;
+
+							auto iterFind2 = mDependantLoads.find(dependency);
+							if (iterFind2 != mDependantLoads.end())
+							{
+								Vector<ResourceLoadData*>& dependantData = iterFind2->second;
+								auto iterFind3 = std::find_if(dependantData.begin(), dependantData.end(),
+									[&](ResourceLoadData* x)
+								{
+									return x->resource.getUUID() == outputResource.getUUID();
+								});
+
+								registerDependency = iterFind3 == dependantData.end();
+							}
+
+							if (registerDependency)
+							{
+								mDependantLoads[dependency].push_back(loadData);
+								loadData->remainingDependencies++;
+							}
+						}
+					}
+				}
+
+				for (auto& dependency : dependencies)
+					loadFromUUID(dependency, !synchronous);
+			}
+		}
 
 		// Actually start the file read operation if not already loaded or in progress
 		if (!alreadyLoading && !filePath.isEmpty())
@@ -439,42 +497,57 @@ namespace BansheeEngine
 		String uuid = resource.getUUID();
 
 		ResourceLoadData* myLoadData = nullptr;
+		bool finishLoad = true;
 		Vector<ResourceLoadData*> dependantLoads;
 		{
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
+
 			auto iterFind = mInProgressResources.find(uuid);
 			if (iterFind != mInProgressResources.end())
 			{
 				myLoadData = iterFind->second;
-				mInProgressResources.erase(iterFind);
+				finishLoad = myLoadData->remainingDependencies == 0;
+				
+				if (finishLoad)
+					mInProgressResources.erase(iterFind);
 			}
 
-			dependantLoads = mDependantLoads[uuid];
-			mDependantLoads.erase(uuid);
-		}
+			auto iterFind2 = mDependantLoads.find(uuid);
 
-		if (myLoadData != nullptr)
-		{
+			if (iterFind2 != mDependantLoads.end())
+				dependantLoads = iterFind2->second;
+
+			if (finishLoad)
 			{
-				BS_LOCK_MUTEX(mLoadedResourceMutex);
-				mLoadedResources[uuid] = resource;
-			}
+				mDependantLoads.erase(uuid);
 
-			resource._setHandleData(myLoadData->loadedData, uuid);
-			onResourceLoaded(resource);
+				// If loadedData is null then we're probably completing load on an already loaded resource, triggered
+				// by its dependencies.
+				if (myLoadData != nullptr && myLoadData->loadedData != nullptr)
+				{
+					BS_LOCK_MUTEX(mLoadedResourceMutex);
 
-			if (myLoadData->notifyImmediately)
-				ResourceListenerManager::instance().notifyListeners(uuid);
+					mLoadedResources[uuid] = resource;
+					resource._setHandleData(myLoadData->loadedData, uuid);
+				}
 
-			bs_delete(myLoadData);
+				for (auto& dependantLoad : dependantLoads)
+					dependantLoad->remainingDependencies--;
+			}
 		}
 
 		for (auto& dependantLoad : dependantLoads)
+			loadComplete(dependantLoad->resource);
+
+		if (finishLoad && myLoadData != nullptr)
 		{
-			dependantLoad->remainingDependencies--;
+			onResourceLoaded(resource);
 
-			if (dependantLoad->remainingDependencies == 0)
-				loadComplete(dependantLoad->resource);
+			// This should only ever be true on the main thread
+			if (myLoadData->notifyImmediately)
+				ResourceListenerManager::instance().notifyListeners(uuid);
+
+			bs_delete(myLoadData);
 		}
 	}
 
@@ -482,7 +555,6 @@ namespace BansheeEngine
 	{
 		ResourcePtr rawResource = loadFromDiskAndDeserialize(filePath);
 
-		bool finishLoad = false;
 		{
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
 
@@ -490,12 +562,9 @@ namespace BansheeEngine
 			ResourceLoadData* myLoadData = mInProgressResources[resource.getUUID()];
 			myLoadData->loadedData = rawResource;
 			myLoadData->remainingDependencies--;
-
-			finishLoad = myLoadData->remainingDependencies == 0;
 		}
 
-		if (finishLoad)
-			loadComplete(resource);
+		loadComplete(resource);
 	}
 
 	BS_CORE_EXPORT Resources& gResources()

+ 0 - 1
MBansheeEditor/EditorApplication.cs

@@ -248,7 +248,6 @@ namespace BansheeEditor
                     scenePath += ".prefab";
 
                     SaveScene(scenePath);
-                    LoadScene(scenePath);
                 }
             }
         }