Ver Fonte

Refactoring resource handles (part 1)

BearishSun há 10 anos atrás
pai
commit
609490dbe6

+ 64 - 31
BansheeCore/Include/BsResourceHandle.h

@@ -13,12 +13,13 @@ namespace BansheeEngine
 	struct BS_CORE_EXPORT ResourceHandleData
 	struct BS_CORE_EXPORT ResourceHandleData
 	{
 	{
 		ResourceHandleData()
 		ResourceHandleData()
-			:mIsCreated(false)
+			:mIsCreated(false), mRefCount(0)
 		{ }
 		{ }
 
 
-		std::shared_ptr<Resource> mPtr;
+		SPtr<Resource> mPtr;
 		String mUUID;
 		String mUUID;
 		bool mIsCreated;	
 		bool mIsCreated;	
+		UINT32 mRefCount;
 	};
 	};
 
 
 	/**
 	/**
@@ -53,7 +54,10 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @brief	Gets the handle data. For internal use only.
 		 * @brief	Gets the handle data. For internal use only.
 		 */
 		 */
-		const std::shared_ptr<ResourceHandleData>& getHandleData() const { return mData; }
+		const SPtr<ResourceHandleData>& getHandleData() const { return mData; }
+
+	protected:
+		ResourceHandleBase();
 
 
 		/**
 		/**
 		 * @brief	Sets the created flag to true and assigns the resource pointer. Called
 		 * @brief	Sets the created flag to true and assigns the resource pointer. Called
@@ -64,22 +68,12 @@ namespace BansheeEngine
 		 *			multithreaded nature of resource loading.
 		 *			multithreaded nature of resource loading.
 		 *			Internal method.
 		 *			Internal method.
 		 */
 		 */
-		void _setHandleData(std::shared_ptr<Resource> ptr, const String& uuid);
-
-		/**
-		 * @brief	Sets the internal handle data to another previously created data.
-		 *
-		 * @note	Internal method.
-		 */
-		void _setHandleData(const std::shared_ptr<ResourceHandleData>& data);
-
-	protected:
-		ResourceHandleBase();
+		void setHandleData(const SPtr<Resource>& ptr, const String& uuid);
 
 
 		/** @note	All handles to the same source must share this same handle data. Otherwise things
 		/** @note	All handles to the same source must share this same handle data. Otherwise things
 		 *			like counting number of references or replacing pointed to resource become impossible
 		 *			like counting number of references or replacing pointed to resource become impossible
 		 *			without additional logic. */
 		 *			without additional logic. */
-		std::shared_ptr<ResourceHandleData> mData;
+		SPtr<ResourceHandleData> mData;
 
 
 	private:
 	private:
 		friend class Resources;
 		friend class Resources;
@@ -115,17 +109,6 @@ namespace BansheeEngine
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{ }
 		{ }
 
 
-		/**
-		 * @brief	Constructs an invalid handle with the specified UUID. You must call _setHandleData
-		 *			with the actual resource pointer to make the handle valid.
-		 */
-		ResourceHandle(const String& uuid)
-			:ResourceHandleBase()
-		{
-			mData = bs_shared_ptr_new<ResourceHandleData>();
-			mData->mUUID = uuid;
-		}
-
 		/**
 		/**
 		 * @brief	Copy constructor.
 		 * @brief	Copy constructor.
 		 */
 		 */
@@ -133,6 +116,15 @@ namespace BansheeEngine
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{
 		{
 			mData = ptr.getHandleData();
 			mData = ptr.getHandleData();
+
+			if (mData != nullptr)
+				mData->mRefCount++;
+		}
+
+		~ResourceHandle()
+		{
+			if (mData != nullptr)
+				mData->mRefCount--;
 		}
 		}
 
 
 		/**
 		/**
@@ -141,7 +133,7 @@ namespace BansheeEngine
 		operator ResourceHandle<Resource>() const
 		operator ResourceHandle<Resource>() const
 		{
 		{
 			ResourceHandle<Resource> handle;
 			ResourceHandle<Resource> handle;
-			handle._setHandleData(getHandleData());
+			handle.setHandleData(getHandleData());
 
 
 			return handle;
 			return handle;
 		}
 		}
@@ -166,6 +158,9 @@ namespace BansheeEngine
 		 */
 		 */
 		ResourceHandle<T>& operator=(std::nullptr_t ptr)
 		ResourceHandle<T>& operator=(std::nullptr_t ptr)
 		{ 	
 		{ 	
+			if (mData != nullptr)
+				mData->mRefCount--;
+
 			mData = nullptr;
 			mData = nullptr;
 			return *this;
 			return *this;
 		}
 		}
@@ -204,7 +199,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Throws exception if handle is invalid.
 		 * @note	Throws exception if handle is invalid.
 		 */
 		 */
-		std::shared_ptr<T> getInternalPtr() const
+		SPtr<T> getInternalPtr() const
 		{ 
 		{ 
 			throwIfNotLoaded();
 			throwIfNotLoaded();
 
 
@@ -213,6 +208,10 @@ namespace BansheeEngine
 
 
 	private:
 	private:
 		friend class Resources;
 		friend class Resources;
+		template<class _Ty1>
+		friend class ResourceHandle;
+		template<class _Ty1, class _Ty2>
+		friend ResourceHandle<_Ty1> static_resource_cast(const ResourceHandle<_Ty2>& other);
 
 
 		/**
 		/**
 		 * @brief	Constructs a new valid handle for the provided resource with the provided UUID.
 		 * @brief	Constructs a new valid handle for the provided resource with the provided UUID.
@@ -224,7 +223,21 @@ namespace BansheeEngine
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{
 		{
 			mData = bs_shared_ptr_new<ResourceHandleData>();
 			mData = bs_shared_ptr_new<ResourceHandleData>();
-			_setHandleData(std::shared_ptr<Resource>(ptr, uuid));
+			mData->mRefCount++;
+
+			setHandleData(std::shared_ptr<Resource>(ptr, uuid));
+		}
+
+		/**
+		 * @brief	Constructs an invalid handle with the specified UUID. You must call setHandleData
+		 *			with the actual resource pointer to make the handle valid.
+		 */
+		ResourceHandle(const String& uuid)
+			:ResourceHandleBase()
+		{
+			mData = bs_shared_ptr_new<ResourceHandleData>();
+			mData->mRefCount++;
+			mData->mUUID = uuid;
 		}
 		}
 
 
 		/**
 		/**
@@ -234,8 +247,28 @@ namespace BansheeEngine
 			:ResourceHandleBase()
 			:ResourceHandleBase()
 		{
 		{
 			mData = bs_shared_ptr_new<ResourceHandleData>();
 			mData = bs_shared_ptr_new<ResourceHandleData>();
-			_setHandleData(ptr, uuid);
+			mData->mRefCount++;
+
+			setHandleData(ptr, uuid);
+		}
+
+		/**
+		 * @brief	Sets the internal handle data to another previously created data.
+		 *
+		 * @note	Internal method.
+		 */
+		void setHandleData(const SPtr<ResourceHandleData>& data)
+		{
+			if (mData != nullptr)
+				mData->mRefCount--;
+
+			mData = data;
+
+			if (mData != nullptr)
+				mData->mRefCount++;
 		}
 		}
+
+		using ResourceHandleBase::setHandleData;
 	};
 	};
 
 
 	/**
 	/**
@@ -245,7 +278,7 @@ namespace BansheeEngine
 		ResourceHandle<_Ty1> static_resource_cast(const ResourceHandle<_Ty2>& other)
 		ResourceHandle<_Ty1> static_resource_cast(const ResourceHandle<_Ty2>& other)
 	{	
 	{	
 		ResourceHandle<_Ty1> handle;
 		ResourceHandle<_Ty1> handle;
-		handle._setHandleData(other.getHandleData());
+		handle.setHandleData(other.getHandleData());
 
 
 		return handle;
 		return handle;
 	}
 	}

+ 9 - 6
BansheeCore/Include/BsResourceHandleRTTI.h

@@ -30,13 +30,15 @@ namespace BansheeEngine
 
 
 			if(resourceHandle->mData && resourceHandle->mData->mUUID != "")
 			if(resourceHandle->mData && resourceHandle->mData->mUUID != "")
 			{
 			{
-				// Note: Resource system needs to be aware of this handle before this point is reached so it
-				// can queue the load. This is handled automatically by Resources but is something to be aware of
-				// if you are loading resources in some other way.
-				HResource loadedResource = gResources()._getResourceHandle(resourceHandle->mData->mUUID);
+				HResource loadedResource = gResources()._createResourceHandle(resourceHandle->mData->mUUID);
 
 
-				if(loadedResource)
-					resourceHandle->_setHandleData(loadedResource.getHandleData());
+				if (resourceHandle->mData != nullptr)
+					resourceHandle->mData->mRefCount--;
+
+				resourceHandle->mData = loadedResource.mData;
+
+				if (resourceHandle->mData != nullptr)
+					resourceHandle->mData->mRefCount++;
 			}
 			}
 		}
 		}
 
 
@@ -55,6 +57,7 @@ namespace BansheeEngine
 		{
 		{
 			std::shared_ptr<ResourceHandleBase> obj = bs_shared_ptr<ResourceHandleBase>(new (bs_alloc<ResourceHandleBase>()) ResourceHandleBase());
 			std::shared_ptr<ResourceHandleBase> obj = bs_shared_ptr<ResourceHandleBase>(new (bs_alloc<ResourceHandleBase>()) ResourceHandleBase());
 			obj->mData = bs_shared_ptr_new<ResourceHandleData>();
 			obj->mData = bs_shared_ptr_new<ResourceHandleData>();
+			obj->mData->mRefCount++;
 
 
 			return obj;
 			return obj;
 		}
 		}

+ 2 - 2
BansheeCore/Include/BsResources.h

@@ -159,9 +159,9 @@ namespace BansheeEngine
 
 
 		/**
 		/**
 		 * @brief	Returns an existing handle of a resource that has already been loaded,
 		 * @brief	Returns an existing handle of a resource that has already been loaded,
-		 *			or is currently being loaded.
+		 *			or is currently being loaded, or creates a new handle for the specified UUID.
 		 */
 		 */
-		HResource _getResourceHandle(const String& uuid);
+		HResource _createResourceHandle(const String& uuid);
 
 
 		/**
 		/**
 		 * @brief	Allows you to set a resource manifest containing UUID <-> file path mapping that is
 		 * @brief	Allows you to set a resource manifest containing UUID <-> file path mapping that is

+ 1 - 6
BansheeCore/Source/BsResourceHandle.cpp

@@ -64,7 +64,7 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ResourceHandleBase::_setHandleData(std::shared_ptr<Resource> ptr, const String& uuid)
+	void ResourceHandleBase::setHandleData(const SPtr<Resource>& ptr, const String& uuid)
 	{
 	{
 		mData->mPtr = ptr;
 		mData->mPtr = ptr;
 
 
@@ -84,11 +84,6 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void ResourceHandleBase::_setHandleData(const std::shared_ptr<ResourceHandleData>& data)
-	{
-		mData = data;
-	}
-
 	void ResourceHandleBase::throwIfNotLoaded() const
 	void ResourceHandleBase::throwIfNotLoaded() const
 	{
 	{
 #if BS_DEBUG_MODE
 #if BS_DEBUG_MODE

+ 9 - 9
BansheeCore/Source/BsResources.cpp

@@ -29,7 +29,7 @@ namespace BansheeEngine
 			unload(loadedResourcePair.second);
 			unload(loadedResourcePair.second);
 
 
 			// Invalidate the handle
 			// Invalidate the handle
-			loadedResourcePair.second._setHandleData(nullptr, "");
+			loadedResourcePair.second.setHandleData(nullptr, "");
 		}
 		}
 	}
 	}
 
 
@@ -307,7 +307,7 @@ namespace BansheeEngine
 
 
 		Vector<ResourceDependency> dependencies = Utility::findResourceDependencies(*resource.get());
 		Vector<ResourceDependency> dependencies = Utility::findResourceDependencies(*resource.get());
 
 
-		// Call this before we actually destroy it
+		// Notify external systems before we actually destroy it
 		onResourceDestroyed(resource);
 		onResourceDestroyed(resource);
 
 
 		resource->destroy();
 		resource->destroy();
@@ -317,14 +317,14 @@ namespace BansheeEngine
 			mLoadedResources.erase(resource.getUUID());
 			mLoadedResources.erase(resource.getUUID());
 		}
 		}
 
 
-		resource._setHandleData(nullptr, "");
+		resource.setHandleData(nullptr, "");
 
 
 		for (auto& dependency : dependencies)
 		for (auto& dependency : dependencies)
 		{
 		{
 			HResource dependantResource = dependency.resource;
 			HResource dependantResource = dependency.resource;
 
 
 			// Last reference was kept by the unloaded resource, so unload the dependency too
 			// Last reference was kept by the unloaded resource, so unload the dependency too
-			if ((UINT32)dependantResource.mData.use_count() == (dependency.numReferences + 1))
+			if ((UINT32)dependantResource.mData->mRefCount == (dependency.numReferences + 1))
 			{
 			{
 				// TODO - Use count is not thread safe. Meaning it might increase after above check, in
 				// TODO - Use count is not thread safe. Meaning it might increase after above check, in
 				// which case we will be unloading a resource that is in use. I don't see a way around 
 				// which case we will be unloading a resource that is in use. I don't see a way around 
@@ -343,7 +343,7 @@ namespace BansheeEngine
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
 			BS_LOCK_MUTEX(mLoadedResourceMutex);
 			for(auto iter = mLoadedResources.begin(); iter != mLoadedResources.end(); ++iter)
 			for(auto iter = mLoadedResources.begin(); iter != mLoadedResources.end(); ++iter)
 			{
 			{
-				if (iter->second.mData.unique()) // We just have this one reference, meaning nothing is using this resource
+				if (iter->second.mData->mRefCount == 1) // We just have this one reference, meaning nothing is using this resource
 					resourcesToUnload.push_back(iter->second);
 					resourcesToUnload.push_back(iter->second);
 			}
 			}
 		}
 		}
@@ -401,7 +401,7 @@ namespace BansheeEngine
 
 
 	void Resources::update(HResource& handle, const ResourcePtr& resource)
 	void Resources::update(HResource& handle, const ResourcePtr& resource)
 	{
 	{
-		handle._setHandleData(resource, handle.getUUID());
+		handle.setHandleData(resource, handle.getUUID());
 
 
 		onResourceModified(handle);
 		onResourceModified(handle);
 	}
 	}
@@ -489,7 +489,7 @@ namespace BansheeEngine
 		return newHandle;
 		return newHandle;
 	}
 	}
 
 
-	HResource Resources::_getResourceHandle(const String& uuid)
+	HResource Resources::_createResourceHandle(const String& uuid)
 	{
 	{
 		{
 		{
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
 			BS_LOCK_MUTEX(mInProgressResourcesMutex);
@@ -509,7 +509,7 @@ namespace BansheeEngine
 			}
 			}
 		}
 		}
 
 
-		return HResource();
+		return HResource(uuid);
 	}
 	}
 
 
 	bool Resources::getFilePathFromUUID(const String& uuid, Path& filePath) const
 	bool Resources::getFilePathFromUUID(const String& uuid, Path& filePath) const
@@ -574,7 +574,7 @@ namespace BansheeEngine
 					BS_LOCK_MUTEX(mLoadedResourceMutex);
 					BS_LOCK_MUTEX(mLoadedResourceMutex);
 
 
 					mLoadedResources[uuid] = resource;
 					mLoadedResources[uuid] = resource;
-					resource._setHandleData(myLoadData->loadedData, uuid);
+					resource.setHandleData(myLoadData->loadedData, uuid);
 				}
 				}
 
 
 				for (auto& dependantLoad : dependantLoads)
 				for (auto& dependantLoad : dependantLoads)

+ 1 - 1
BansheeD3D11RenderAPI/Source/BsD3D11InputLayoutManager.cpp

@@ -143,7 +143,7 @@ namespace BansheeEngine
 		newEntry->inputLayout = nullptr; 
 		newEntry->inputLayout = nullptr; 
 		HRESULT hr = device.getD3D11Device()->CreateInputLayout( 
 		HRESULT hr = device.getD3D11Device()->CreateInputLayout( 
 			&declElements[0], 
 			&declElements[0], 
-			declElements.size(),
+			(UINT32)declElements.size(),
 			&microcode[0], 
 			&microcode[0], 
 			microcode.size(),
 			microcode.size(),
 			&newEntry->inputLayout);
 			&newEntry->inputLayout);

+ 2 - 5
BansheeEditor/Source/BsProjectLibrary.cpp

@@ -437,13 +437,10 @@ namespace BansheeEngine
 
 
 				if (!isNativeResource)
 				if (!isNativeResource)
 				{
 				{
-					importedResource = gResources()._getResourceHandle(resource->meta->getUUID());
+					importedResource = gResources()._createResourceHandle(resource->meta->getUUID());
 
 
-					if (importedResource == nullptr)
-					{
-						importedResource = HResource(resource->meta->getUUID());
+					if (!importedResource.isLoaded(false))
 						unloadWhenDone = true;
 						unloadWhenDone = true;
-					}
 
 
 					Importer::instance().reimport(importedResource, resource->path, curImportOptions);
 					Importer::instance().reimport(importedResource, resource->path, curImportOptions);
 				}
 				}