Przeglądaj źródła

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 lat temu
rodzic
commit
00b3967714

+ 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
 		// Actually start the file read operation if not already loaded or in progress
 		if (!alreadyLoading && !filePath.isEmpty())
 		if (!alreadyLoading && !filePath.isEmpty())
@@ -439,42 +497,57 @@ namespace BansheeEngine
 		String uuid = resource.getUUID();
 		String uuid = resource.getUUID();
 
 
 		ResourceLoadData* myLoadData = nullptr;
 		ResourceLoadData* myLoadData = nullptr;
+		bool finishLoad = true;
 		Vector<ResourceLoadData*> dependantLoads;
 		Vector<ResourceLoadData*> dependantLoads;
 		{
 		{
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
+
 			auto iterFind = mInProgressResources.find(uuid);
 			auto iterFind = mInProgressResources.find(uuid);
 			if (iterFind != mInProgressResources.end())
 			if (iterFind != mInProgressResources.end())
 			{
 			{
 				myLoadData = iterFind->second;
 				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)
 		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);
 		ResourcePtr rawResource = loadFromDiskAndDeserialize(filePath);
 
 
-		bool finishLoad = false;
 		{
 		{
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
 
 
@@ -490,12 +562,9 @@ namespace BansheeEngine
 			ResourceLoadData* myLoadData = mInProgressResources[resource.getUUID()];
 			ResourceLoadData* myLoadData = mInProgressResources[resource.getUUID()];
 			myLoadData->loadedData = rawResource;
 			myLoadData->loadedData = rawResource;
 			myLoadData->remainingDependencies--;
 			myLoadData->remainingDependencies--;
-
-			finishLoad = myLoadData->remainingDependencies == 0;
 		}
 		}
 
 
-		if (finishLoad)
-			loadComplete(resource);
+		loadComplete(resource);
 	}
 	}
 
 
 	BS_CORE_EXPORT Resources& gResources()
 	BS_CORE_EXPORT Resources& gResources()

+ 0 - 1
MBansheeEditor/EditorApplication.cs

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