Ver Fonte

MeshHeap refactored to comply with new CoreObject design
Added shared this ptr to CoreObjectCore objects

Marko Pintera há 11 anos atrás
pai
commit
6e60df9371

+ 13 - 0
BansheeCore/Include/BsCoreObjectCore.h

@@ -30,6 +30,18 @@ namespace BansheeEngine
 		 */
 		virtual void destroy();
 
+		/**
+		 * @brief	Internal method. Sets a shared this pointer to this object. This MUST be called immediately after construction.
+		 *
+		 * @note	Called automatically by the factory creation methods so user should not call this manually.
+		 */
+		void _setThisPtr(std::shared_ptr<CoreObjectCore> ptrThis);
+
+		/**
+		 * @brief	Returns a shared_ptr version of "this" pointer.
+		 */
+		SPtr<CoreObjectCore> getThisPtr() const { return mThis.lock(); }
+
 	protected:
 		friend class CoreObjectManager;
 		friend class CoreObject;
@@ -76,5 +88,6 @@ namespace BansheeEngine
 
 		UINT32 mCoreDirtyFlags;
 		bool mIsDestroyed;
+		std::weak_ptr<CoreObjectCore> mThis;
 	};
 }

+ 1 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -151,6 +151,7 @@ namespace BansheeEngine
 	struct SubMesh;
 	class TransientMeshCore;
 	class TextureCore;
+	class MeshHeapCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;

+ 106 - 87
BansheeCore/Include/BsMeshHeap.h

@@ -8,22 +8,13 @@
 namespace BansheeEngine
 {
 	/**
-	 * @brief	Mesh heap allows you to quickly allocate and deallocate a large amounts of temporary 
-	 *			meshes without the large overhead of normal Mesh creation.
-	 * 			Only requirement is that meshes share the same vertex description and index type.
-	 * 			
-	 * @note	This class should be considered as a replacement for a normal Mesh if you are constantly 
-	 * 			updating the mesh (e.g. every frame) and you are not able to discard entire mesh contents 
-	 * 			on each update. Not using discard flag on normal meshes may introduce GPU-CPU sync points
-	 * 			which may severely limit performance. Primary purpose of this class is to avoid
-	 * 			those sync points by not forcing you to discard contents.
-	 * 			
-	 *			Downside is that this class may allocate 2-3x (or more) memory than it is actually needed
-	 *			for your data.
-	 *			
-	 *			Sim thread except where noted otherwise.
+	 * @brief	Core thread version of MeshHeap.
+	 *
+	 * @see		MeshHeap
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_CORE_EXPORT MeshHeap : public CoreObject
+	class BS_CORE_EXPORT MeshHeapCore : public CoreObjectCore
 	{
 		/**
 		 * @brief	Signifies how is a data chunk used.
@@ -66,102 +57,59 @@ namespace BansheeEngine
 			UINT32 queryId;
 		};
 
-	public:
-		~MeshHeap();
-
-		/**
-		 * @brief	Allocates a new mesh in the heap, expanding the heap if needed. Mesh will be initialized
-		 *			with the provided meshData. You may use the returned transient mesh for drawing.
-		 *
-		 * @note	Offsets provided by MeshData are ignored. MeshHeap will determine
-		 * 			where the data will be written internally.
-		 */
-		TransientMeshPtr alloc(const MeshDataPtr& meshData, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
-
-		/**
-		 * @brief	Deallocates the provided mesh and makes that room on the heap re-usable as soon as the GPU
-		 *			is also done with the mesh.
-		 */
-		void dealloc(const TransientMeshPtr& mesh);
-
-		/**
-		 * @brief	Creates a new mesh heap.
-		 *
-		 * @param	numVertices	Initial number of vertices the heap may store. This will grow automatically if needed.
-		 * @param	numIndices	Initial number of indices the heap may store. This will grow automatically if needed.
-		 * @param	vertexDesc	Description of the stored vertices.
-		 * @param	indexType	Type of the stored indices.
-		 */
-		static MeshHeapPtr create(UINT32 numVertices, UINT32 numIndices, 
-			const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
-
 	private:
+		friend class MeshHeap;
 		friend class TransientMesh;
 		friend class TransientMeshCore;
 
-		/**
-		 * @copydoc	create
-		 */
-		MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+		MeshHeapCore(UINT32 numVertices, UINT32 numIndices, 
 			const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
 
 		/**
-		 * @copydoc CoreObject::initialize_internal()
+		 * @copydoc CoreObjectCore::initialize()
 		 */
-		virtual void initialize_internal();
+		virtual void initialize();
 
 		/**
-		 * @copydoc CoreObject::destroy_internal()
+		 * @copydoc CoreObjectCore::destroy()
 		 */
-		virtual void destroy_internal();
+		virtual void destroy();
 
 		/**
 		 * @brief	Allocates a new mesh in the heap, expanding the heap if needed. 
 		 *
 		 * @param	meshId		Mesh for which we are allocating the data.
 		 * @param	meshData	Data to initialize the new mesh with.
-		 *
-		 * @note	Core thread.
 		 */
-		void allocInternal(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData);
+		void alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData);
 
 		/**
 		 * @brief	Deallocates the provided mesh Freed memory
 		 *			will be re-used as soon as the GPU is done with the mesh
-		 *
-		 * @note	Core thread.
 		 */
-		void deallocInternal(SPtr<TransientMeshCore> mesh);
+		void dealloc(SPtr<TransientMeshCore> mesh);
 
 		/**
 		 * @brief	Resizes the vertex buffers so they max contain the provided
 		 *			number of vertices.
-		 *
-		 * @note	Core thread.
 		 */
 		void growVertexBuffer(UINT32 numVertices);
 
 		/**
 		 * @brief	Resizes the index buffer so they max contain the provided
 		 *			number of indices.
-		 *
-		 * @note	Core thread.
 		 */
 		void growIndexBuffer(UINT32 numIndices);
 
 		/**
 		 * @brief	Creates a new event query or returns an existing one from the pool
 		 *			if available. Returned value is an index into mEventQueries array.
-		 *
-		 * @note	Core thread.
 		 */
 		UINT32 createEventQuery();
 
 		/**
 		 * @brief	Frees the event query with the specified index and returns it to the
 		 *			pool so it may be reused later.
-		 *
-		 * @note	Core thread.
 		 */
 		void freeEventQuery(UINT32 idx);
 
@@ -196,7 +144,7 @@ namespace BansheeEngine
 		 * @brief	Called by an GPU event query when GPU processes the query. Normally
 		 *			signals the heap that the GPU is done with the mesh.
 		 */
-		static void queryTriggered(MeshHeapPtr thisPtr, UINT32 meshId, UINT32 queryId);
+		static void queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId);
 
 		/**
 		 * @brief	Attempts to reorganize the vertex and index buffer chunks in order to 
@@ -208,37 +156,108 @@ namespace BansheeEngine
 		void mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx);
 
 	private:
-		UINT32 mNumVertices; // Core thread
-		UINT32 mNumIndices; // Core thread
-
-		Vector<UINT8*> mCPUVertexData; // Core thread
-		UINT8* mCPUIndexData; // Core thread
+		UINT32 mNumVertices;
+		UINT32 mNumIndices;
 
-		SPtr<VertexData> mVertexData; // Core thread
-		SPtr<IndexBufferCore> mIndexBuffer; // Core thread
+		Vector<UINT8*> mCPUVertexData;
+		UINT8* mCPUIndexData;
 
-		Map<UINT32, AllocatedData> mMeshAllocData; // Core thread
+		SPtr<VertexData> mVertexData;
+		SPtr<IndexBufferCore> mIndexBuffer;
 
-		VertexDataDescPtr mVertexDesc; // Immutable
-		IndexType mIndexType; // Immutable
+		Map<UINT32, AllocatedData> mMeshAllocData;
 
-		Map<UINT32, TransientMeshPtr> mMeshes; // Sim thread
-		UINT32 mNextFreeId; // Sim thread
+		VertexDataDescPtr mVertexDesc;
+		IndexType mIndexType;
 
-		Vector<ChunkData> mVertChunks; // Core thread
-		Vector<ChunkData> mIdxChunks; // Core thread
+		Vector<ChunkData> mVertChunks;
+		Vector<ChunkData> mIdxChunks;
 
-		Stack<UINT32> mEmptyVertChunks; // Core thread
-		Stack<UINT32> mEmptyIdxChunks; // Core thread
+		Stack<UINT32> mEmptyVertChunks;
+		Stack<UINT32> mEmptyIdxChunks;
 
-		List<UINT32> mFreeVertChunks; // Core thread
-		List<UINT32> mFreeIdxChunks; // Core thread
+		List<UINT32> mFreeVertChunks;
+		List<UINT32> mFreeIdxChunks;
 
-		Vector<QueryData> mEventQueries; // Core thread
-		Stack<UINT32> mFreeEventQueries; // Core thread
+		Vector<QueryData> mEventQueries; 
+		Stack<UINT32> mFreeEventQueries;
 
 		UINT32 mNextQueryId;
 
 		static const float GrowPercent;
 	};
+
+	/**
+	 * @brief	Mesh heap allows you to quickly allocate and deallocate a large amounts of temporary 
+	 *			meshes without the large overhead of normal Mesh creation.
+	 * 			Only requirement is that meshes share the same vertex description and index type.
+	 * 			
+	 * @note	This class should be considered as a replacement for a normal Mesh if you are constantly 
+	 * 			updating the mesh (e.g. every frame) and you are not able to discard entire mesh contents 
+	 * 			on each update. Not using discard flag on normal meshes may introduce GPU-CPU sync points
+	 * 			which may severely limit performance. Primary purpose of this class is to avoid
+	 * 			those sync points by not forcing you to discard contents.
+	 * 			
+	 *			Downside is that this class may allocate 2-3x (or more) memory than it is actually needed
+	 *			for your data.
+	 *			
+	 *			Sim thread only
+	 */
+	class BS_CORE_EXPORT MeshHeap : public CoreObject
+	{
+	public:
+		/**
+		 * @brief	Allocates a new mesh in the heap, expanding the heap if needed. Mesh will be initialized
+		 *			with the provided meshData. You may use the returned transient mesh for drawing.
+		 *
+		 * @note	Offsets provided by MeshData are ignored. MeshHeap will determine
+		 * 			where the data will be written internally.
+		 */
+		TransientMeshPtr alloc(const MeshDataPtr& meshData, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
+
+		/**
+		 * @brief	Deallocates the provided mesh and makes that room on the heap re-usable as soon as the GPU
+		 *			is also done with the mesh.
+		 */
+		void dealloc(const TransientMeshPtr& mesh);
+
+		/**
+		 * @brief	Retrieves a core implementation of a mesh heap usable only from the
+		 *			core thread.
+		 */
+		SPtr<MeshHeapCore> getCore() const;
+
+		/**
+		 * @brief	Creates a new mesh heap.
+		 *
+		 * @param	numVertices	Initial number of vertices the heap may store. This will grow automatically if needed.
+		 * @param	numIndices	Initial number of indices the heap may store. This will grow automatically if needed.
+		 * @param	vertexDesc	Description of the stored vertices.
+		 * @param	indexType	Type of the stored indices.
+		 */
+		static MeshHeapPtr create(UINT32 numVertices, UINT32 numIndices, 
+			const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
+
+	private:
+		/**
+		 * @copydoc	create
+		 */
+		MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+			const VertexDataDescPtr& vertexDesc, IndexType indexType = IT_32BIT);
+
+		/**
+		 * @copydoc	RenderTarget::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const;
+
+	private:
+		UINT32 mNumVertices;
+		UINT32 mNumIndices;
+
+		VertexDataDescPtr mVertexDesc;
+		IndexType mIndexType;
+
+		Map<UINT32, TransientMeshPtr> mMeshes;
+		UINT32 mNextFreeId;
+	};
 }

+ 2 - 2
BansheeCore/Include/BsTransientMesh.h

@@ -15,7 +15,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TransientMeshCore : public MeshCoreBase
 	{
 	public:
-		TransientMeshCore(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices,
+		TransientMeshCore(const SPtr<MeshHeapCore>& parentHeap, UINT32 id, UINT32 numVertices,
 			UINT32 numIndices, const Vector<SubMesh>& subMeshes);
 
 		/**
@@ -51,7 +51,7 @@ namespace BansheeEngine
 	protected:
 		friend class TransientMesh;
 
-		MeshHeapPtr mParentHeap;
+		SPtr<MeshHeapCore> mParentHeap;
 		UINT32 mId;
 	};
 

+ 5 - 0
BansheeCore/Source/BsCoreObjectCore.cpp

@@ -22,4 +22,9 @@ namespace BansheeEngine
 
 		mIsDestroyed = true;
 	}
+
+	void CoreObjectCore::_setThisPtr(std::shared_ptr<CoreObjectCore> ptrThis)
+	{
+		mThis = ptrThis;
+	}
 }

+ 8 - 2
BansheeCore/Source/BsGpuProgramManager.cpp

@@ -44,12 +44,18 @@ namespace BansheeEngine
 		SPtr<GpuProgramCore> create(const String& source, const String& entryPoint, GpuProgramType gptype, 
 			GpuProgramProfile profile, bool requiresAdjacencyInformation)
 		{
-			return bs_shared_ptr<NullProgramCore>();
+			SPtr<NullProgramCore> ret = bs_shared_ptr<NullProgramCore>();
+			ret->_setThisPtr(ret);
+
+			return ret;
 		}
 
 		SPtr<GpuProgramCore> create(GpuProgramType type)
 		{
-			return bs_shared_ptr<NullProgramCore>();
+			SPtr<NullProgramCore> ret = bs_shared_ptr<NullProgramCore>();
+			ret->_setThisPtr(ret);
+
+			return ret;
 		}
 	};
 

+ 2 - 0
BansheeCore/Source/BsMesh.cpp

@@ -394,6 +394,8 @@ namespace BansheeEngine
 			mVertexDesc, mProperties.mSubMeshes, mBufferType, mIndexType, mTempInitialMeshData);
 
 		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<MeshCore, GenAlloc>(obj);
+		meshCore->_setThisPtr(meshCore);
+
 		mTempInitialMeshData = nullptr;
 
 		return meshCore;

+ 148 - 131
BansheeCore/Source/BsMeshHeap.cpp

@@ -10,48 +10,30 @@
 
 namespace BansheeEngine
 {
-	const float MeshHeap::GrowPercent = 1.5f;
+	const float MeshHeapCore::GrowPercent = 1.5f;
 
-	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+	MeshHeapCore::MeshHeapCore(UINT32 numVertices, UINT32 numIndices,
 		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
-		mIndexType(indexType), mVertexDesc(vertexDesc), mCPUIndexData(nullptr),
-		mNextQueryId(0)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mIndexType(indexType), 
+		mVertexDesc(vertexDesc), mCPUIndexData(nullptr), mNextQueryId(0)
 	{
-		for(UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
 		{
 			mCPUVertexData.push_back(nullptr);
 		}
 	}
 
-	MeshHeap::~MeshHeap()
-	{
-
-	}
-
-	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
-		const VertexDataDescPtr& vertexDesc, IndexType indexType)
-	{
-		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
-		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap, GenAlloc>(meshHeap);
-
-		meshHeapPtr->_setThisPtr(meshHeapPtr);
-		meshHeapPtr->initialize();
-
-		return meshHeapPtr;
-	}
-
-	void MeshHeap::initialize_internal()
+	void MeshHeapCore::initialize()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		growVertexBuffer(mNumVertices);
 		growIndexBuffer(mNumIndices);
 
-		CoreObject::initialize_internal();
+		CoreObjectCore::initialize();
 	}
 
-	void MeshHeap::destroy_internal()
+	void MeshHeapCore::destroy()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -77,53 +59,23 @@ namespace BansheeEngine
 		mIndexBuffer = nullptr;
 		mVertexDesc = nullptr;
 
-		CoreObject::destroy_internal();
-	}
-
-	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
-	{
-		UINT32 meshIdx = mNextFreeId++;
-
-		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
-		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
-		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh, GenAlloc>(transientMesh);
-
-		transientMeshPtr->_setThisPtr(transientMeshPtr);
-		transientMeshPtr->initialize();
-
-		mMeshes[meshIdx] = transientMeshPtr;
-
-		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::allocInternal, this, transientMeshPtr->getCore(), meshData));
-
-		return transientMeshPtr;
-	}
-
-	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
-	{
-		auto iterFind = mMeshes.find(mesh->mId);
-		if(iterFind == mMeshes.end())
-			return;
-
-		mesh->markAsDestroyed();
-		mMeshes.erase(iterFind);
-
-		queueGpuCommand(getThisPtr(), std::bind(&MeshHeap::deallocInternal, this, mesh->getCore()));
+		CoreObjectCore::destroy();
 	}
 
-	void MeshHeap::allocInternal(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
+	void MeshHeapCore::alloc(SPtr<TransientMeshCore> mesh, const MeshDataPtr& meshData)
 	{
 		// Find free vertex chunk and grow if needed
 		UINT32 smallestVertFit = 0;
 		UINT32 smallestVertFitIdx = 0;
 
-		while(smallestVertFit == 0)
+		while (smallestVertFit == 0)
 		{
 			UINT32 curIdx = 0;
-			for(auto& chunkIdx : mFreeVertChunks)
+			for (auto& chunkIdx : mFreeVertChunks)
 			{
 				ChunkData& chunk = mVertChunks[chunkIdx];
 
-				if(chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
+				if (chunk.size >= meshData->getNumVertices() && (chunk.size < smallestVertFit || smallestVertFit == 0))
 				{
 					smallestVertFit = chunk.size;
 					smallestVertFitIdx = curIdx;
@@ -132,11 +84,11 @@ namespace BansheeEngine
 				curIdx++;
 			}
 
-			if(smallestVertFit > 0)
+			if (smallestVertFit > 0)
 				break;
 
 			UINT32 newNumVertices = mNumVertices;
-			while(newNumVertices < (mNumVertices + meshData->getNumVertices()))
+			while (newNumVertices < (mNumVertices + meshData->getNumVertices()))
 			{
 				newNumVertices = Math::roundToInt(newNumVertices * GrowPercent);
 			}
@@ -148,14 +100,14 @@ namespace BansheeEngine
 		UINT32 smallestIdxFit = 0;
 		UINT32 smallestIdxFitIdx = 0;
 
-		while(smallestIdxFit == 0)
+		while (smallestIdxFit == 0)
 		{
 			UINT32 curIdx = 0;
-			for(auto& chunkIdx : mFreeIdxChunks)
+			for (auto& chunkIdx : mFreeIdxChunks)
 			{
 				ChunkData& chunk = mIdxChunks[chunkIdx];
 
-				if(chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
+				if (chunk.size >= meshData->getNumIndices() && (chunk.size < smallestIdxFit || smallestIdxFit == 0))
 				{
 					smallestIdxFit = chunk.size;
 					smallestIdxFitIdx = curIdx;
@@ -164,11 +116,11 @@ namespace BansheeEngine
 				curIdx++;
 			}
 
-			if(smallestIdxFit > 0)
+			if (smallestIdxFit > 0)
 				break;
 
 			UINT32 newNumIndices = mNumIndices;
-			while(newNumIndices < (mNumIndices + meshData->getNumIndices()))
+			while (newNumIndices < (mNumIndices + meshData->getNumIndices()))
 			{
 				newNumIndices = Math::roundToInt(newNumIndices * GrowPercent);
 			}
@@ -181,17 +133,17 @@ namespace BansheeEngine
 
 		auto freeVertIter = mFreeVertChunks.begin();
 		freeVertChunkIdx = (*freeVertIter);
-		for(UINT32 i = 0; i < smallestVertFitIdx; i++)
+		for (UINT32 i = 0; i < smallestVertFitIdx; i++)
 		{
 			freeVertIter++;
 			freeVertChunkIdx = (*freeVertIter);
 		}
 
 		mFreeVertChunks.erase(freeVertIter);
-		
+
 		auto freeIdxIter = mFreeIdxChunks.begin();
 		freeIdxChunkIdx = (*freeIdxIter);
-		for(UINT32 i = 0; i < smallestIdxFitIdx; i++)
+		for (UINT32 i = 0; i < smallestIdxFitIdx; i++)
 		{
 			freeIdxIter++;
 			freeIdxChunkIdx = (*freeIdxIter);
@@ -211,9 +163,9 @@ namespace BansheeEngine
 		vertChunk.size = meshData->getNumVertices();
 		idxChunk.size = meshData->getNumIndices();
 
-		if(remainingNumVerts > 0)
+		if (remainingNumVerts > 0)
 		{
-			if(!mEmptyVertChunks.empty())
+			if (!mEmptyVertChunks.empty())
 			{
 				UINT32 emptyChunkIdx = mEmptyVertChunks.top();
 				ChunkData& emptyChunk = mVertChunks[emptyChunkIdx];
@@ -233,9 +185,9 @@ namespace BansheeEngine
 			}
 		}
 
-		if(remainingNumIdx > 0)
+		if (remainingNumIdx > 0)
 		{
-			if(!mEmptyIdxChunks.empty())
+			if (!mEmptyIdxChunks.empty())
 			{
 				UINT32 emptyChunkIdx = mEmptyIdxChunks.top();
 				ChunkData& emptyChunk = mIdxChunks[emptyChunkIdx];
@@ -265,20 +217,20 @@ namespace BansheeEngine
 		mMeshAllocData[mesh->getMeshHeapId()] = newAllocData;
 
 		// Actually copy data
-		for(UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
 		{
-			if(!mVertexDesc->hasStream(i))
+			if (!mVertexDesc->hasStream(i))
 				continue;
 
-			if(!meshData->getVertexDesc()->hasStream(i))
+			if (!meshData->getVertexDesc()->hasStream(i))
 				continue;
 
 			// Ensure vertex sizes match
 			UINT32 vertSize = mVertexData->vertexDeclaration->getVertexSize(i);
 			UINT32 otherVertSize = meshData->getVertexDesc()->getVertexStride(i);
-			if(otherVertSize != vertSize)
+			if (otherVertSize != vertSize)
 			{
-				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " + 
+				BS_EXCEPT(InvalidParametersException, "Provided vertex size for stream " + toString(i) + " doesn't match meshes vertex size. Needed: " +
 					toString(vertSize) + ". Got: " + toString(otherVertSize));
 			}
 
@@ -291,9 +243,9 @@ namespace BansheeEngine
 			if (RenderSystem::instance().getVertexColorFlipRequired())
 			{
 				UINT32 vertexStride = mVertexDesc->getVertexStride(i);
-				for(INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
+				for (INT32 semanticIdx = 0; semanticIdx < VertexBuffer::MAX_SEMANTIC_IDX; semanticIdx++)
 				{
-					if(!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
+					if (!mVertexDesc->hasElement(VES_COLOR, semanticIdx, i))
 						continue;
 
 					UINT8* colorData = vertDest + mVertexDesc->getElementOffsetFromStream(VES_COLOR, semanticIdx, i);
@@ -316,9 +268,9 @@ namespace BansheeEngine
 		UINT32 idxSize = ibProps.getIndexSize();
 
 		// Ensure index sizes match
-		if(meshData->getIndexElementSize() != idxSize)
+		if (meshData->getIndexElementSize() != idxSize)
 		{
-			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " + 
+			BS_EXCEPT(InvalidParametersException, "Provided index size doesn't match meshes index size. Needed: " +
 				toString(idxSize) + ". Got: " + toString(meshData->getIndexElementSize()));
 		}
 
@@ -327,13 +279,13 @@ namespace BansheeEngine
 		mIndexBuffer->writeData(idxChunkStart * idxSize, meshData->getNumIndices() * idxSize, idxDest, BufferWriteType::NoOverwrite);
 	}
 
-	void MeshHeap::deallocInternal(SPtr<TransientMeshCore> mesh)
+	void MeshHeapCore::dealloc(SPtr<TransientMeshCore> mesh)
 	{
 		auto findIter = mMeshAllocData.find(mesh->getMeshHeapId());
 		assert(findIter != mMeshAllocData.end());
 
 		AllocatedData& allocData = findIter->second;
-		if(allocData.useFlags == UseFlags::GPUFree)
+		if (allocData.useFlags == UseFlags::GPUFree)
 		{
 			allocData.useFlags = UseFlags::Free;
 			freeEventQuery(allocData.eventQueryIdx);
@@ -345,11 +297,11 @@ namespace BansheeEngine
 
 			mMeshAllocData.erase(findIter);
 		}
-		else if(allocData.useFlags == UseFlags::Used)
+		else if (allocData.useFlags == UseFlags::Used)
 			allocData.useFlags = UseFlags::CPUFree;
 	}
 
-	void MeshHeap::growVertexBuffer(UINT32 numVertices)
+	void MeshHeapCore::growVertexBuffer(UINT32 numVertices)
 	{
 		mNumVertices = numVertices;
 		mVertexData = std::shared_ptr<VertexData>(bs_new<VertexData, PoolAlloc>());
@@ -358,9 +310,9 @@ namespace BansheeEngine
 		mVertexData->vertexDeclaration = mVertexDesc->createDeclaration();
 
 		// Create buffers and copy data
-		for(UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
+		for (UINT32 i = 0; i <= mVertexDesc->getMaxStreamIdx(); i++)
 		{
-			if(!mVertexDesc->hasStream(i))
+			if (!mVertexDesc->hasStream(i))
 				continue;
 
 			UINT32 vertSize = mVertexData->vertexDeclaration->getVertexSize(i);
@@ -374,9 +326,9 @@ namespace BansheeEngine
 			UINT8* buffer = (UINT8*)bs_alloc(vertSize * numVertices);
 
 			UINT32 destOffset = 0;
-			if(oldBuffer != nullptr)
+			if (oldBuffer != nullptr)
 			{
-				for(auto& allocData : mMeshAllocData)
+				for (auto& allocData : mMeshAllocData)
 				{
 					ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
 
@@ -389,7 +341,7 @@ namespace BansheeEngine
 				bs_free(oldBuffer);
 			}
 
-			if(destOffset > 0)
+			if (destOffset > 0)
 				vertexBuffer->writeData(0, destOffset * vertSize, buffer, BufferWriteType::NoOverwrite);
 
 			mCPUVertexData[i] = buffer;
@@ -400,7 +352,7 @@ namespace BansheeEngine
 		Vector<ChunkData> newVertChunks;
 		List<UINT32> freeVertChunks;
 
-		for(auto& allocData : mMeshAllocData)
+		for (auto& allocData : mMeshAllocData)
 		{
 			ChunkData& oldChunk = mVertChunks[allocData.second.vertChunkIdx];
 
@@ -415,7 +367,7 @@ namespace BansheeEngine
 		}
 
 		// Add free chunk
-		if(destOffset != mNumVertices)
+		if (destOffset != mNumVertices)
 		{
 			ChunkData newChunk;
 			newChunk.start = destOffset;
@@ -427,12 +379,12 @@ namespace BansheeEngine
 
 		mVertChunks = newVertChunks;
 		mFreeVertChunks = freeVertChunks;
-		
-		while(!mEmptyVertChunks.empty())
+
+		while (!mEmptyVertChunks.empty())
 			mEmptyVertChunks.pop();
 	}
 
-	void MeshHeap::growIndexBuffer(UINT32 numIndices)
+	void MeshHeapCore::growIndexBuffer(UINT32 numIndices)
 	{
 		mNumIndices = numIndices;
 
@@ -446,9 +398,9 @@ namespace BansheeEngine
 		UINT8* buffer = (UINT8*)bs_alloc(idxSize * numIndices);
 
 		UINT32 destOffset = 0;
-		if(oldBuffer != nullptr)
+		if (oldBuffer != nullptr)
 		{
-			for(auto& allocData : mMeshAllocData)
+			for (auto& allocData : mMeshAllocData)
 			{
 				ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
 
@@ -461,7 +413,7 @@ namespace BansheeEngine
 			bs_free(oldBuffer);
 		}
 
-		if(destOffset > 0)
+		if (destOffset > 0)
 			mIndexBuffer->writeData(0, destOffset * idxSize, buffer, BufferWriteType::NoOverwrite);
 
 		mCPUIndexData = buffer;
@@ -471,7 +423,7 @@ namespace BansheeEngine
 		Vector<ChunkData> newIdxChunks;
 		List<UINT32> freeIdxChunks;
 
-		for(auto& allocData : mMeshAllocData)
+		for (auto& allocData : mMeshAllocData)
 		{
 			ChunkData& oldChunk = mIdxChunks[allocData.second.idxChunkIdx];
 
@@ -486,7 +438,7 @@ namespace BansheeEngine
 		}
 
 		// Add free chunk
-		if(destOffset != mNumIndices)
+		if (destOffset != mNumIndices)
 		{
 			ChunkData newChunk;
 			newChunk.start = destOffset;
@@ -499,14 +451,14 @@ namespace BansheeEngine
 		mIdxChunks = newIdxChunks;
 		mFreeIdxChunks = freeIdxChunks;
 
-		while(!mEmptyIdxChunks.empty())
+		while (!mEmptyIdxChunks.empty())
 			mEmptyIdxChunks.pop();
 	}
 
-	UINT32 MeshHeap::createEventQuery()
+	UINT32 MeshHeapCore::createEventQuery()
 	{
 		UINT32 idx = 0;
-		if(mFreeEventQueries.size() > 0)
+		if (mFreeEventQueries.size() > 0)
 		{
 			idx = mFreeEventQueries.top();
 			mFreeEventQueries.pop();
@@ -524,24 +476,24 @@ namespace BansheeEngine
 		return idx;
 	}
 
-	void MeshHeap::freeEventQuery(UINT32 idx)
+	void MeshHeapCore::freeEventQuery(UINT32 idx)
 	{
 		mEventQueries[idx].query->onTriggered.clear();
 		mEventQueries[idx].queryId = 0;
 		mFreeEventQueries.push(idx);
 	}
 
-	SPtr<VertexData> MeshHeap::getVertexData() const
+	SPtr<VertexData> MeshHeapCore::getVertexData() const
 	{
 		return mVertexData;
 	}
 
-	SPtr<IndexBufferCore> MeshHeap::getIndexBuffer() const
+	SPtr<IndexBufferCore> MeshHeapCore::getIndexBuffer() const
 	{
 		return mIndexBuffer;
 	}
 
-	UINT32 MeshHeap::getVertexOffset(UINT32 meshId) const
+	UINT32 MeshHeapCore::getVertexOffset(UINT32 meshId) const
 	{
 		auto findIter = mMeshAllocData.find(meshId);
 		assert(findIter != mMeshAllocData.end());
@@ -550,7 +502,7 @@ namespace BansheeEngine
 		return mVertChunks[chunkIdx].start;
 	}
 
-	UINT32 MeshHeap::getIndexOffset(UINT32 meshId) const
+	UINT32 MeshHeapCore::getIndexOffset(UINT32 meshId) const
 	{
 		auto findIter = mMeshAllocData.find(meshId);
 		assert(findIter != mMeshAllocData.end());
@@ -559,7 +511,7 @@ namespace BansheeEngine
 		return mIdxChunks[chunkIdx].start;
 	}
 
-	void MeshHeap::notifyUsedOnGPU(UINT32 meshId)
+	void MeshHeapCore::notifyUsedOnGPU(UINT32 meshId)
 	{
 		auto findIter = mMeshAllocData.find(meshId);
 		assert(findIter != mMeshAllocData.end());
@@ -567,20 +519,20 @@ namespace BansheeEngine
 		AllocatedData& allocData = findIter->second;
 		assert(allocData.useFlags != UseFlags::Free);
 
-		if(allocData.useFlags == UseFlags::GPUFree)
+		if (allocData.useFlags == UseFlags::GPUFree)
 			allocData.useFlags = UseFlags::Used;
 
-		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
+		SPtr<MeshHeapCore> thisPtr = std::static_pointer_cast<MeshHeapCore>(getThisPtr());
 
 		QueryData& queryData = mEventQueries[allocData.eventQueryIdx];
 		queryData.queryId = mNextQueryId++;
 		queryData.query->onTriggered.clear();
-		queryData.query->onTriggered.connect(std::bind(&MeshHeap::queryTriggered, thisPtr, meshId, queryData.queryId));
+		queryData.query->onTriggered.connect(std::bind(&MeshHeapCore::queryTriggered, thisPtr, meshId, queryData.queryId));
 		queryData.query->begin();
 	}
 
 	// Note: Need to use a shared ptr here to ensure MeshHeap doesn't get deallocated sometime during this callback
-	void MeshHeap::queryTriggered(MeshHeapPtr thisPtr, UINT32 meshId, UINT32 queryId)
+	void MeshHeapCore::queryTriggered(SPtr<MeshHeapCore> thisPtr, UINT32 meshId, UINT32 queryId)
 	{
 		auto findIter = thisPtr->mMeshAllocData.find(meshId);
 		assert(findIter != thisPtr->mMeshAllocData.end());
@@ -590,11 +542,11 @@ namespace BansheeEngine
 		// If query ids don't match then it means there either a more recent query or
 		// the buffer was discarded and we are not interested in query result
 		QueryData& queryData = thisPtr->mEventQueries[allocData.eventQueryIdx];
-		if(queryId == queryData.queryId) 
+		if (queryId == queryData.queryId)
 		{
 			assert(allocData.useFlags != UseFlags::Free && allocData.useFlags != UseFlags::GPUFree);
 
-			if(allocData.useFlags == UseFlags::CPUFree)
+			if (allocData.useFlags == UseFlags::CPUFree)
 			{
 				allocData.useFlags = UseFlags::Free;
 				thisPtr->freeEventQuery(allocData.eventQueryIdx);
@@ -613,27 +565,27 @@ namespace BansheeEngine
 		queryData.query->onTriggered.clear();
 	}
 
-	void MeshHeap::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
+	void MeshHeapCore::mergeWithNearbyChunks(UINT32 chunkVertIdx, UINT32 chunkIdxIdx)
 	{
 		// Merge vertex chunks
 		ChunkData& vertChunk = mVertChunks[chunkVertIdx];
-		for(auto& freeChunkIdx : mFreeVertChunks)
+		for (auto& freeChunkIdx : mFreeVertChunks)
 		{
-			if(chunkVertIdx == freeChunkIdx)
+			if (chunkVertIdx == freeChunkIdx)
 				continue;
 
 			ChunkData& curChunk = mVertChunks[freeChunkIdx];
-			if(curChunk.size == 0) // Already merged
+			if (curChunk.size == 0) // Already merged
 				continue;
 
 			bool merged = false;
-			if(curChunk.start == (vertChunk.start + vertChunk.size))
+			if (curChunk.start == (vertChunk.start + vertChunk.size))
 			{
 				vertChunk.size += curChunk.size;
 
 				merged = true;
 			}
-			else if((curChunk.start + curChunk.size) == vertChunk.start)
+			else if ((curChunk.start + curChunk.size) == vertChunk.start)
 			{
 				vertChunk.start = curChunk.start;
 				vertChunk.size += curChunk.size;
@@ -641,7 +593,7 @@ namespace BansheeEngine
 				merged = true;
 			}
 
-			if(merged)
+			if (merged)
 			{
 				// We can't remove the chunk since that would break the indexing scheme, so 
 				// mark it as empty and set size to 0. It will be reused when needed.
@@ -653,23 +605,23 @@ namespace BansheeEngine
 
 		// Merge index chunks
 		ChunkData& idxChunk = mIdxChunks[chunkIdxIdx];
-		for(auto& freeChunkIdx : mFreeIdxChunks)
+		for (auto& freeChunkIdx : mFreeIdxChunks)
 		{
-			if(chunkIdxIdx == freeChunkIdx)
+			if (chunkIdxIdx == freeChunkIdx)
 				continue;
 
 			ChunkData& curChunk = mIdxChunks[freeChunkIdx];
-			if(curChunk.size == 0) // Already merged
+			if (curChunk.size == 0) // Already merged
 				continue;
 
 			bool merged = false;
-			if(curChunk.start == (idxChunk.start + idxChunk.size))
+			if (curChunk.start == (idxChunk.start + idxChunk.size))
 			{
 				idxChunk.size += curChunk.size;
 
 				merged = true;
 			}
-			else if((curChunk.start + curChunk.size) == idxChunk.start)
+			else if ((curChunk.start + curChunk.size) == idxChunk.start)
 			{
 				idxChunk.start = curChunk.start;
 				idxChunk.size += curChunk.size;
@@ -677,7 +629,7 @@ namespace BansheeEngine
 				merged = true;
 			}
 
-			if(merged)
+			if (merged)
 			{
 				// We can't remove the chunk since that would break the indexing scheme, so 
 				// mark it as empty and set size to 0. It will be reused when needed.
@@ -687,4 +639,69 @@ namespace BansheeEngine
 			}
 		}
 	}
+
+	MeshHeap::MeshHeap(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+		:mNumVertices(numVertices), mNumIndices(numIndices), mNextFreeId(0), 
+		mIndexType(indexType), mVertexDesc(vertexDesc)
+	{
+	}
+
+	MeshHeapPtr MeshHeap::create(UINT32 numVertices, UINT32 numIndices, 
+		const VertexDataDescPtr& vertexDesc, IndexType indexType)
+	{
+		MeshHeap* meshHeap = new (bs_alloc<MeshHeap>()) MeshHeap(numVertices, numIndices, vertexDesc, indexType); 
+		MeshHeapPtr meshHeapPtr = bs_core_ptr<MeshHeap, GenAlloc>(meshHeap);
+
+		meshHeapPtr->_setThisPtr(meshHeapPtr);
+		meshHeapPtr->initialize();
+
+		return meshHeapPtr;
+	}
+
+	TransientMeshPtr MeshHeap::alloc(const MeshDataPtr& meshData, DrawOperationType drawOp)
+	{
+		UINT32 meshIdx = mNextFreeId++;
+
+		MeshHeapPtr thisPtr = std::static_pointer_cast<MeshHeap>(getThisPtr());
+		TransientMesh* transientMesh = new (bs_alloc<TransientMesh>()) TransientMesh(thisPtr, meshIdx, meshData->getNumVertices(), meshData->getNumIndices(), drawOp); 
+		TransientMeshPtr transientMeshPtr = bs_core_ptr<TransientMesh, GenAlloc>(transientMesh);
+
+		transientMeshPtr->_setThisPtr(transientMeshPtr);
+		transientMeshPtr->initialize();
+
+		mMeshes[meshIdx] = transientMeshPtr;
+
+		queueGpuCommand(getThisPtr(), std::bind(&MeshHeapCore::alloc, getCore().get(), transientMeshPtr->getCore(), meshData));
+
+		return transientMeshPtr;
+	}
+
+	void MeshHeap::dealloc(const TransientMeshPtr& mesh)
+	{
+		auto iterFind = mMeshes.find(mesh->mId);
+		if(iterFind == mMeshes.end())
+			return;
+
+		mesh->markAsDestroyed();
+		mMeshes.erase(iterFind);
+
+		queueGpuCommand(getThisPtr(), std::bind(&MeshHeapCore::dealloc, getCore().get(), mesh->getCore()));
+	}
+
+	SPtr<MeshHeapCore> MeshHeap::getCore() const
+	{
+		return std::static_pointer_cast<MeshHeapCore>(mCoreSpecific);
+	}
+
+	SPtr<CoreObjectCore> MeshHeap::createCore() const
+	{
+		MeshHeapCore* obj = new (bs_alloc<MeshHeapCore>()) MeshHeapCore(mNumVertices, mNumIndices,
+			mVertexDesc, mIndexType);
+
+		SPtr<MeshHeapCore> corePtr = bs_shared_ptr<MeshHeapCore, GenAlloc>(obj);
+		obj->_setThisPtr(corePtr);
+
+		return corePtr;
+	}
 }

+ 4 - 0
BansheeCore/Source/BsRenderStateManager.cpp

@@ -145,6 +145,7 @@ namespace BansheeEngine
 	SPtr<SamplerStateCore> RenderStateCoreManager::createSamplerStateInternal(const SAMPLER_STATE_DESC& desc) const
 	{
 		SPtr<SamplerStateCore> samplerState = bs_shared_ptr<SamplerStateCore, GenAlloc>(new (bs_alloc<SamplerStateCore>()) SamplerStateCore(desc));
+		samplerState->_setThisPtr(samplerState);
 
 		return samplerState;
 	}
@@ -152,6 +153,7 @@ namespace BansheeEngine
 	SPtr<DepthStencilStateCore> RenderStateCoreManager::createDepthStencilStateInternal(const DEPTH_STENCIL_STATE_DESC& desc) const
 	{
 		SPtr<DepthStencilStateCore> depthStencilState = bs_shared_ptr<DepthStencilStateCore, GenAlloc>(new (bs_alloc<DepthStencilStateCore>()) DepthStencilStateCore(desc));
+		depthStencilState->_setThisPtr(depthStencilState);
 
 		return depthStencilState;
 	}
@@ -159,6 +161,7 @@ namespace BansheeEngine
 	SPtr<RasterizerStateCore> RenderStateCoreManager::createRasterizerStateInternal(const RASTERIZER_STATE_DESC& desc) const
 	{
 		SPtr<RasterizerStateCore> rasterizerState = bs_shared_ptr<RasterizerStateCore, GenAlloc>(new (bs_alloc<RasterizerStateCore>()) RasterizerStateCore(desc));
+		rasterizerState->_setThisPtr(rasterizerState);
 
 		return rasterizerState;
 	}
@@ -166,6 +169,7 @@ namespace BansheeEngine
 	SPtr<BlendStateCore> RenderStateCoreManager::createBlendStateInternal(const BLEND_STATE_DESC& desc) const
 	{
 		SPtr<BlendStateCore> blendState = bs_shared_ptr<BlendStateCore, GenAlloc>(new (bs_alloc<BlendStateCore>()) BlendStateCore(desc));
+		blendState->_setThisPtr(blendState);
 
 		return blendState;
 	}

+ 5 - 2
BansheeCore/Source/BsTransientMesh.cpp

@@ -6,7 +6,8 @@
 
 namespace BansheeEngine
 {
-	TransientMeshCore::TransientMeshCore(const MeshHeapPtr& parentHeap, UINT32 id, UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
+	TransientMeshCore::TransientMeshCore(const SPtr<MeshHeapCore>& parentHeap, UINT32 id, 
+		UINT32 numVertices, UINT32 numIndices, const Vector<SubMesh>& subMeshes)
 		:MeshCoreBase(numVertices, numIndices, subMeshes), mParentHeap(parentHeap), mId(id)
 	{
 
@@ -60,9 +61,11 @@ namespace BansheeEngine
 	SPtr<CoreObjectCore> TransientMesh::createCore() const
 	{
 		TransientMeshCore* core = new (bs_alloc<TransientMeshCore>()) TransientMeshCore(
-			mParentHeap, mId, mProperties.mNumVertices, mProperties.mNumIndices, mProperties.mSubMeshes);
+			mParentHeap->getCore(), mId, mProperties.mNumVertices, mProperties.mNumIndices, mProperties.mSubMeshes);
 
 		SPtr<CoreObjectCore> meshCore = bs_shared_ptr<TransientMeshCore, GenAlloc>(core);
+		meshCore->_setThisPtr(meshCore);
+
 		return meshCore;
 	}
 }

+ 22 - 12
BansheeD3D11RenderSystem/Source/BsD3D11HLSLProgramFactory.cpp

@@ -21,49 +21,59 @@ namespace BansheeEngine
 	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(const String& source, const String& entryPoint,
 		GpuProgramType gptype, GpuProgramProfile profile, bool requireAdjacencyInfo)
     {
+		SPtr<GpuProgramCore> gpuProg;
+
 		switch (gptype)
 		{
 		case GPT_VERTEX_PROGRAM:
-			return bs_shared_ptr<D3D11GpuVertexProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuVertexProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuVertexProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuVertexProgramCore, GenAlloc>())
 				D3D11GpuVertexProgramCore(source, entryPoint, profile));
 		case GPT_FRAGMENT_PROGRAM:
-			return bs_shared_ptr<D3D11GpuFragmentProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuFragmentProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuFragmentProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuFragmentProgramCore, GenAlloc>())
 				D3D11GpuFragmentProgramCore(source, entryPoint, profile));
 		case GPT_HULL_PROGRAM:
-			return bs_shared_ptr<D3D11GpuHullProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuHullProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuHullProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuHullProgramCore, GenAlloc>())
 				D3D11GpuHullProgramCore(source, entryPoint, profile));
 		case GPT_DOMAIN_PROGRAM:
-			return bs_shared_ptr<D3D11GpuDomainProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuDomainProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuDomainProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuDomainProgramCore, GenAlloc>())
 				D3D11GpuDomainProgramCore(source, entryPoint, profile));
 		case GPT_GEOMETRY_PROGRAM:
-			return bs_shared_ptr<D3D11GpuGeometryProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuGeometryProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuGeometryProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuGeometryProgramCore, GenAlloc>())
 				D3D11GpuGeometryProgramCore(source, entryPoint, profile, requireAdjacencyInfo));
 		}
 
-		return nullptr;
+		if (gpuProg != nullptr)
+			gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
     }
 
 	SPtr<GpuProgramCore> D3D11HLSLProgramFactory::create(GpuProgramType type)
 	{
+		SPtr<GpuProgramCore> gpuProg;
+
 		switch (type)
 		{
 		case GPT_VERTEX_PROGRAM:
-			return bs_shared_ptr<D3D11GpuVertexProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuVertexProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuVertexProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuVertexProgramCore, GenAlloc>())
 				D3D11GpuVertexProgramCore("", "", GPP_NONE));
 		case GPT_FRAGMENT_PROGRAM:
-			return bs_shared_ptr<D3D11GpuFragmentProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuFragmentProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuFragmentProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuFragmentProgramCore, GenAlloc>())
 				D3D11GpuFragmentProgramCore("", "", GPP_NONE));
 		case GPT_HULL_PROGRAM:
-			return bs_shared_ptr<D3D11GpuHullProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuHullProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuHullProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuHullProgramCore, GenAlloc>())
 				D3D11GpuHullProgramCore("", "", GPP_NONE));
 		case GPT_DOMAIN_PROGRAM:
-			return bs_shared_ptr<D3D11GpuDomainProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuDomainProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuDomainProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuDomainProgramCore, GenAlloc>())
 				D3D11GpuDomainProgramCore("", "", GPP_NONE));
 		case GPT_GEOMETRY_PROGRAM:
-			return bs_shared_ptr<D3D11GpuGeometryProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuGeometryProgramCore, GenAlloc>())
+			gpuProg = bs_shared_ptr<D3D11GpuGeometryProgramCore, GenAlloc>(new (bs_alloc<D3D11GpuGeometryProgramCore, GenAlloc>())
 				D3D11GpuGeometryProgramCore("", "", GPP_NONE, false));
 		}
 
-		return nullptr;
+		if (gpuProg != nullptr)
+			gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
 	}
 }

+ 8 - 2
BansheeD3D11RenderSystem/Source/BsD3D11HardwareBufferManager.cpp

@@ -33,13 +33,19 @@ namespace BansheeEngine
 	SPtr<VertexBufferCore> D3D11HardwareBufferCoreManager::createVertexBufferInternal(UINT32 vertexSize,
 		UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
 	{
-		return bs_shared_ptr<D3D11VertexBufferCore>(mDevice, vertexSize, numVerts, usage, streamOut);
+		SPtr<D3D11VertexBufferCore> ret = bs_shared_ptr<D3D11VertexBufferCore>(mDevice, vertexSize, numVerts, usage, streamOut);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<IndexBufferCore> D3D11HardwareBufferCoreManager::createIndexBufferInternal(IndexType itype,
 		UINT32 numIndexes, GpuBufferUsage usage)
 	{
-		return bs_shared_ptr<D3D11IndexBufferCore>(mDevice, itype, numIndexes, usage);
+		SPtr<D3D11IndexBufferCore> ret = bs_shared_ptr<D3D11IndexBufferCore>(mDevice, itype, numIndexes, usage);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 }

+ 16 - 4
BansheeD3D11RenderSystem/Source/BsD3D11RenderStateManager.cpp

@@ -8,21 +8,33 @@ namespace BansheeEngine
 {
 	SPtr<SamplerStateCore> D3D11RenderStateCoreManager::createSamplerStateInternal(const SAMPLER_STATE_DESC& desc) const
 	{
-		return bs_shared_ptr<D3D11SamplerStateCore, GenAlloc>(new (bs_alloc<D3D11SamplerStateCore>()) D3D11SamplerStateCore(desc));
+		SPtr<SamplerStateCore> ret = bs_shared_ptr<D3D11SamplerStateCore, GenAlloc>(new (bs_alloc<D3D11SamplerStateCore>()) D3D11SamplerStateCore(desc));
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<BlendStateCore> D3D11RenderStateCoreManager::createBlendStateInternal(const BLEND_STATE_DESC& desc) const
 	{
-		return bs_shared_ptr<D3D11BlendStateCore, GenAlloc>(new (bs_alloc<D3D11BlendStateCore>()) D3D11BlendStateCore(desc));
+		SPtr<BlendStateCore> ret = bs_shared_ptr<D3D11BlendStateCore, GenAlloc>(new (bs_alloc<D3D11BlendStateCore>()) D3D11BlendStateCore(desc));
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<RasterizerStateCore> D3D11RenderStateCoreManager::createRasterizerStateInternal(const RASTERIZER_STATE_DESC& desc) const
 	{
-		return bs_shared_ptr<D3D11RasterizerStateCore, GenAlloc>(new (bs_alloc<D3D11RasterizerStateCore>()) D3D11RasterizerStateCore(desc));
+		SPtr<RasterizerStateCore> ret = bs_shared_ptr<D3D11RasterizerStateCore, GenAlloc>(new (bs_alloc<D3D11RasterizerStateCore>()) D3D11RasterizerStateCore(desc));
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<DepthStencilStateCore> D3D11RenderStateCoreManager::createDepthStencilStateInternal(const DEPTH_STENCIL_STATE_DESC& desc) const
 	{
-		return bs_shared_ptr<D3D11DepthStencilStateCore, GenAlloc>(new (bs_alloc<D3D11DepthStencilStateCore>()) D3D11DepthStencilStateCore(desc));
+		SPtr<DepthStencilStateCore> ret = bs_shared_ptr<D3D11DepthStencilStateCore, GenAlloc>(new (bs_alloc<D3D11DepthStencilStateCore>()) D3D11DepthStencilStateCore(desc));
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 }

+ 5 - 1
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindowManager.cpp

@@ -41,8 +41,12 @@ namespace BansheeEngine
 
 		// Create the window
 		D3D11RenderWindowCore* renderWindow = new (bs_alloc<D3D11RenderWindowCore, GenAlloc>()) D3D11RenderWindowCore(desc, d3d11rs->getPrimaryDevice(), d3d11rs->getDXGIFactory());
+
+		SPtr<D3D11RenderWindowCore> renderWindowPtr = bs_shared_ptr<D3D11RenderWindowCore, GenAlloc>(renderWindow);
+		renderWindowPtr->_setThisPtr(renderWindowPtr);
+
 		windowCreated(renderWindow);
 
-		return bs_shared_ptr<D3D11RenderWindowCore, GenAlloc>(renderWindow);
+		return renderWindowPtr;
 	}
 }

+ 12 - 3
BansheeD3D11RenderSystem/Source/BsD3D11TextureManager.cpp

@@ -35,16 +35,25 @@ namespace BansheeEngine
 		D3D11TextureCore* tex = new (bs_alloc<D3D11TextureCore>()) D3D11TextureCore(texType, 
 			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
 
-		return bs_shared_ptr<D3D11TextureCore, GenAlloc>(tex);
+		SPtr<D3D11TextureCore> texPtr = bs_shared_ptr<D3D11TextureCore, GenAlloc>(tex);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<RenderTextureCore> D3D11TextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<D3D11RenderTextureCore>(desc);
+		SPtr<D3D11RenderTextureCore> texPtr = bs_shared_ptr<D3D11RenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<MultiRenderTextureCore> D3D11TextureCoreManager::createMultiRenderTextureInternal(const MULTI_RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<D3D11MultiRenderTextureCore>(desc);
+		SPtr<D3D11MultiRenderTextureCore> texPtr = bs_shared_ptr<D3D11MultiRenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 }

+ 16 - 6
BansheeD3D9RenderSystem/Source/BsD3D9HLSLProgramFactory.cpp

@@ -21,41 +21,51 @@ namespace BansheeEngine
 	SPtr<GpuProgramCore> D3D9HLSLProgramFactory::create(const String& source, const String& entryPoint,
 		GpuProgramType gptype, GpuProgramProfile profile, bool requiresAdjacency)
     {
+		SPtr<GpuProgramCore> gpuProg;
+
 		if (gptype == GPT_VERTEX_PROGRAM)
 		{
 			D3D9GpuVertexProgramCore* prog = new (bs_alloc<D3D9GpuVertexProgramCore, GenAlloc>())
 				D3D9GpuVertexProgramCore(source, entryPoint, profile);
 
-			return bs_shared_ptr<D3D9GpuVertexProgramCore, GenAlloc>(prog);
+			gpuProg = bs_shared_ptr<D3D9GpuVertexProgramCore, GenAlloc>(prog);
 		}
 		else if (gptype == GPT_FRAGMENT_PROGRAM)
 		{
 			D3D9GpuFragmentProgramCore* prog = new (bs_alloc<D3D9GpuFragmentProgramCore, GenAlloc>())
 				D3D9GpuFragmentProgramCore(source, entryPoint, profile);
 
-			return bs_shared_ptr<D3D9GpuFragmentProgramCore, GenAlloc>(prog);
+			gpuProg = bs_shared_ptr<D3D9GpuFragmentProgramCore, GenAlloc>(prog);
 		}
 
-		return nullptr;
+		if (gpuProg != nullptr)
+			gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
     }
 
 	SPtr<GpuProgramCore> D3D9HLSLProgramFactory::create(GpuProgramType type)
 	{
+		SPtr<GpuProgramCore> gpuProg;
+
 		if (type == GPT_VERTEX_PROGRAM)
 		{
 			D3D9GpuVertexProgramCore* prog = new (bs_alloc<D3D9GpuVertexProgramCore, GenAlloc>())
 				D3D9GpuVertexProgramCore("", "", GPP_NONE);
 
-			return bs_shared_ptr<D3D9GpuVertexProgramCore, GenAlloc>(prog);
+			gpuProg = bs_shared_ptr<D3D9GpuVertexProgramCore, GenAlloc>(prog);
 		}
 		else if (type == GPT_FRAGMENT_PROGRAM)
 		{
 			D3D9GpuFragmentProgramCore* prog = new (bs_alloc<D3D9GpuFragmentProgramCore, GenAlloc>())
 				D3D9GpuFragmentProgramCore("", "", GPP_NONE);
 
-			return bs_shared_ptr<D3D9GpuFragmentProgramCore, GenAlloc>(prog);
+			gpuProg = bs_shared_ptr<D3D9GpuFragmentProgramCore, GenAlloc>(prog);
 		}
 
-		return nullptr;
+		if (gpuProg != nullptr)
+			gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
 	}
 }

+ 8 - 2
BansheeD3D9RenderSystem/Source/BsD3D9HardwareBufferManager.cpp

@@ -31,13 +31,19 @@ namespace BansheeEngine
 	{
 		assert(numVerts > 0);
 
-		return bs_shared_ptr<D3D9VertexBufferCore>(vertexSize, numVerts, usage, streamOut);
+		SPtr<D3D9VertexBufferCore> ret = bs_shared_ptr<D3D9VertexBufferCore>(vertexSize, numVerts, usage, streamOut);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<IndexBufferCore> D3D9HardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
 	{
 		assert(numIndexes > 0);
 
-		return bs_shared_ptr<D3D9IndexBufferCore>(itype, numIndexes, usage);
+		SPtr<D3D9IndexBufferCore> ret = bs_shared_ptr<D3D9IndexBufferCore>(itype, numIndexes, usage);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 }

+ 5 - 1
BansheeD3D9RenderSystem/Source/BsD3D9RenderWindowManager.cpp

@@ -34,8 +34,12 @@ namespace BansheeEngine
 	SPtr<RenderWindowCore> D3D9RenderWindowCoreManager::createInternal(RENDER_WINDOW_DESC& desc)
 	{
 		D3D9RenderWindowCore* window = new (bs_alloc<D3D9RenderWindowCore, GenAlloc>()) D3D9RenderWindowCore(desc, mRenderSystem->getInstanceHandle());
+
+		SPtr<D3D9RenderWindowCore> renderWindowPtr = bs_shared_ptr<D3D9RenderWindowCore, GenAlloc>(window);
+		renderWindowPtr->_setThisPtr(renderWindowPtr);
+
 		windowCreated(window);
 
-		return bs_shared_ptr<D3D9RenderWindowCore, GenAlloc>(window);
+		return renderWindowPtr;
 	}
 }

+ 12 - 3
BansheeD3D9RenderSystem/Source/BsD3D9TextureManager.cpp

@@ -52,16 +52,25 @@ namespace BansheeEngine
 		D3D9TextureCore* tex = new (bs_alloc<D3D9TextureCore>()) D3D9TextureCore(texType,
 			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
 
-		return bs_shared_ptr<D3D9TextureCore, GenAlloc>(tex);
+		SPtr<D3D9TextureCore> texPtr = bs_shared_ptr<D3D9TextureCore, GenAlloc>(tex);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<RenderTextureCore> D3D9TextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<D3D9RenderTextureCore>(desc);
+		SPtr<D3D9RenderTextureCore> texPtr = bs_shared_ptr<D3D9RenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<MultiRenderTextureCore> D3D9TextureCoreManager::createMultiRenderTextureInternal(const MULTI_RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<D3D9MultiRenderTextureCore>(desc);
+		SPtr<D3D9MultiRenderTextureCore> texPtr = bs_shared_ptr<D3D9MultiRenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 }

+ 8 - 2
BansheeGLRenderSystem/Source/BsGLHardwareBufferManager.cpp

@@ -22,12 +22,18 @@ namespace BansheeEngine
 
 	SPtr<VertexBufferCore> GLHardwareBufferCoreManager::createVertexBufferInternal(UINT32 vertexSize, UINT32 numVerts, GpuBufferUsage usage, bool streamOut)
 	{
-		return bs_shared_ptr<GLVertexBufferCore>(vertexSize, numVerts, usage, streamOut);
+		SPtr<GLVertexBufferCore> ret = bs_shared_ptr<GLVertexBufferCore>(vertexSize, numVerts, usage, streamOut);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
 	SPtr<IndexBufferCore> GLHardwareBufferCoreManager::createIndexBufferInternal(IndexType itype, UINT32 numIndexes, GpuBufferUsage usage)
 	{
-		return bs_shared_ptr<GLIndexBufferCore>(itype, numIndexes, usage);
+		SPtr<GLIndexBufferCore> ret = bs_shared_ptr<GLIndexBufferCore>(itype, numIndexes, usage);
+		ret->_setThisPtr(ret);
+
+		return ret;
 	}
 
     GLenum GLHardwareBufferCoreManager::getGLUsage(GpuBufferUsage usage)

+ 2 - 0
BansheeGLRenderSystem/Source/BsGLRenderWindowManager.cpp

@@ -31,6 +31,8 @@ namespace BansheeEngine
 
 		// Create the window
 		SPtr<RenderWindowCore> window = glSupport->newWindowCore(desc);
+		window->_setThisPtr(window);
+
 		windowCreated(window.get());
 
 		return window;

+ 12 - 3
BansheeGLRenderSystem/Source/BsGLTextureManager.cpp

@@ -70,16 +70,25 @@ namespace BansheeEngine
 		GLTextureCore* tex = new (bs_alloc<GLTextureCore>()) GLTextureCore(mGLSupport, texType,
 			width, height, depth, numMips, format, usage, hwGammaCorrection, multisampleCount);
 
-		return bs_shared_ptr<GLTextureCore, GenAlloc>(tex);
+		SPtr<GLTextureCore> texPtr = bs_shared_ptr<GLTextureCore, GenAlloc>(tex);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<RenderTextureCore> GLTextureCoreManager::createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<GLRenderTextureCore>(desc);
+		SPtr<GLRenderTextureCore> texPtr = bs_shared_ptr<GLRenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 
 	SPtr<MultiRenderTextureCore> GLTextureCoreManager::createMultiRenderTextureInternal(const MULTI_RENDER_TEXTURE_DESC& desc)
 	{
-		return bs_shared_ptr<GLMultiRenderTextureCore>(desc);
+		SPtr<GLMultiRenderTextureCore> texPtr = bs_shared_ptr<GLMultiRenderTextureCore>(desc);
+		texPtr->_setThisPtr(texPtr);
+
+		return texPtr;
 	}
 }

+ 8 - 2
BansheeGLRenderSystem/Source/GLSL/src/BsGLSLProgramFactory.cpp

@@ -15,13 +15,19 @@ namespace BansheeEngine
     {
 		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore, GenAlloc>()) GLSLGpuProgramCore(source, entryPoint, gptype, profile, requireAdjacency);
 
-		return bs_shared_ptr<GLSLGpuProgramCore, GenAlloc>(prog);
+		SPtr<GLSLGpuProgramCore> gpuProg = bs_shared_ptr<GLSLGpuProgramCore, GenAlloc>(prog);
+		gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
     }
 
 	SPtr<GpuProgramCore> GLSLProgramFactory::create(GpuProgramType type)
 	{
 		GLSLGpuProgramCore* prog = new (bs_alloc<GLSLGpuProgramCore, GenAlloc>()) GLSLGpuProgramCore("", "", type, GPP_NONE, false);
 
-		return bs_shared_ptr<GLSLGpuProgramCore, GenAlloc>(prog);
+		SPtr<GLSLGpuProgramCore> gpuProg = bs_shared_ptr<GLSLGpuProgramCore, GenAlloc>(prog);
+		gpuProg->_setThisPtr(gpuProg);
+
+		return gpuProg;
 	}
 }

+ 0 - 1
TODO.txt

@@ -2,7 +2,6 @@
 
 TODO - CoreObject refactor:
 Resource
- - GpuProgram
  - Material -> Remove MaterialProxy
  - Shader -> Remove ShaderProxy
 MeshHeap