Ver código fonte

More work on multithreading. Actually managed to reach the main loop now.
Refactoring how resources get destroyed

Marko Pintera 13 anos atrás
pai
commit
9d0b41f349
31 arquivos alterados com 243 adições e 138 exclusões
  1. 0 2
      CamelotD3D9Renderer/Include/CmD3D9GpuProgramManager.h
  2. 1 1
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h
  3. 45 49
      CamelotD3D9Renderer/Include/CmD3D9Texture.h
  4. 0 10
      CamelotD3D9Renderer/Source/CmD3D9GpuProgramManager.cpp
  5. 1 1
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp
  6. 0 21
      CamelotD3D9Renderer/Source/CmD3D9Texture.cpp
  7. 2 0
      CamelotFBXImporter/Source/CmFBXImporter.cpp
  8. 2 0
      CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp
  9. 5 3
      CamelotGLRenderer/Include/CmGLTexture.h
  10. 1 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgramFactory.h
  11. 1 1
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp
  12. 1 0
      CamelotRenderer/CamelotRenderer.vcxproj
  13. 3 0
      CamelotRenderer/CamelotRenderer.vcxproj.filters
  14. 1 1
      CamelotRenderer/Include/CmCgProgramFactory.h
  15. 17 0
      CamelotRenderer/Include/CmGpuProgram.h
  16. 1 1
      CamelotRenderer/Include/CmGpuProgramManager.h
  17. 3 1
      CamelotRenderer/Include/CmHighLevelGpuProgramManager.h
  18. 10 2
      CamelotRenderer/Include/CmMesh.h
  19. 5 0
      CamelotRenderer/Include/CmResourceHandle.h
  20. 9 1
      CamelotRenderer/Include/CmResources.h
  21. 6 0
      CamelotRenderer/Include/CmSpecificImporter.h
  22. 12 5
      CamelotRenderer/Include/CmTexture.h
  23. 1 1
      CamelotRenderer/Source/CmCgProgramFactory.cpp
  24. 13 0
      CamelotRenderer/Source/CmGpuProgram.cpp
  25. 1 1
      CamelotRenderer/Source/CmGpuProgramManager.cpp
  26. 14 4
      CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp
  27. 33 2
      CamelotRenderer/Source/CmMesh.cpp
  28. 30 16
      CamelotRenderer/Source/CmResources.cpp
  29. 10 0
      CamelotRenderer/Source/CmSpecificImporter.cpp
  30. 13 12
      CamelotRenderer/Source/CmTexture.cpp
  31. 2 2
      CamelotRenderer/Source/CmTextureManager.cpp

+ 0 - 2
CamelotD3D9Renderer/Include/CmD3D9GpuProgramManager.h

@@ -36,8 +36,6 @@ namespace CamelotEngine {
 
     class CM_D3D9_EXPORT D3D9GpuProgramManager : public GpuProgramManager
     {
-    public:
-		GpuProgramPtr createProgram(const String& code, GpuProgramType gptype, const String& syntaxCode);
     public:
         D3D9GpuProgramManager();
 		~D3D9GpuProgramManager();

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h

@@ -45,7 +45,7 @@ namespace CamelotEngine
 		const String& getLanguage(void) const;
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
-		void destroy(HighLevelGpuProgram* prog);
+		void destroy_internal(HighLevelGpuProgram* prog);
 
     };
 }

+ 45 - 49
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -38,7 +38,50 @@ THE SOFTWARE.
 namespace CamelotEngine {
 	class CM_D3D9_EXPORT D3D9Texture : public Texture, public D3D9Resource
 	{
+		public:
+		/// destructor
+		~D3D9Texture();
+
+		/// overridden from Texture
+		void copy_internal( TexturePtr& target );
+
+		/// @copydoc Texture::getBuffer
+		HardwarePixelBufferPtr getBuffer_internal(size_t face, size_t mipmap);
+		
+		/// retrieves a pointer to the actual texture
+		IDirect3DBaseTexture9 *getTexture_internal();		
+		/// retrieves a pointer to the normal 1D/2D texture
+		IDirect3DTexture9 *getNormTexture_internal();
+		/// retrieves a pointer to the cube texture
+		IDirect3DCubeTexture9 *getCubeTexture_internal();
+
+		/** Indicates whether the hardware gamma is actually enabled and supported. 
+		@remarks
+			Because hardware gamma might not actually be supported, we need to 
+			ignore it sometimes. Because D3D doesn't encode sRGB in the format but
+			as a sampler state, and we don't want to change the original requested
+			hardware gamma flag (e.g. serialisation) we need another indicator.
+		*/
+		bool isHardwareGammaReadToBeUsed() const { return mHwGamma && mHwGammaReadSupported; }
+					
+		/// Will this texture need to be in the default pool?
+		bool useDefaultPool();
+
+		// Called immediately after the Direct3D device has been created.
+		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
+
+		// Called before the Direct3D device is going to be destroyed.
+		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
+
+		// Called immediately after the Direct3D device has entered a lost state.
+		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
+
+		// Called immediately after the Direct3D device has been reset
+		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);	
+
 	protected:	
+		friend class D3D9TextureManager;
+		friend class D3D9HardwarePixelBuffer;
 
 		struct TextureResources
 		{
@@ -60,7 +103,6 @@ namespace CamelotEngine {
 		/// Map between device to texture resources.
 		DeviceToTextureResourcesMap	mMapDeviceToTextureResources;
 
-
 		/// Vector of pointers to subsurfaces
 		typedef vector<HardwarePixelBufferPtr>::type SurfaceList;
 		SurfaceList	mSurfaceList;
@@ -78,6 +120,8 @@ namespace CamelotEngine {
 		D3DMULTISAMPLE_TYPE mFSAAType;
 		DWORD mFSAAQuality;
 
+		D3D9Texture();
+
 		/// overriden from Resource
 		void initialize_internal();	
 
@@ -93,10 +137,6 @@ namespace CamelotEngine {
 
 		/// @copydoc Resource::calculateSize
 		size_t calculateSize(void) const;
-		/// @copydoc Texture::createInternalResources
-		void createInternalResources(void);
-		/// @copydoc Texture::freeInternalResources
-		void freeInternalResources(void);
 		/// @copydoc Texture::createInternalResourcesImpl
 		void createInternalResourcesImpl(void);
 		/// Creates this texture resources on the specified device.
@@ -136,50 +176,6 @@ namespace CamelotEngine {
 		void freeTextureResources(IDirect3DDevice9* d3d9Device, TextureResources* textureResources);
 
 		void determinePool();
-
-		friend class D3D9HardwarePixelBuffer;
-	public:
-		/// constructor 
-        D3D9Texture();
-		/// destructor
-		~D3D9Texture();
-
-		/// overridden from Texture
-		void copy_internal( TexturePtr& target );
-
-		/// @copydoc Texture::getBuffer
-		HardwarePixelBufferPtr getBuffer_internal(size_t face, size_t mipmap);
-		
-		/// retrieves a pointer to the actual texture
-		IDirect3DBaseTexture9 *getTexture_internal();		
-		/// retrieves a pointer to the normal 1D/2D texture
-		IDirect3DTexture9 *getNormTexture_internal();
-		/// retrieves a pointer to the cube texture
-		IDirect3DCubeTexture9 *getCubeTexture_internal();
-
-		/** Indicates whether the hardware gamma is actually enabled and supported. 
-		@remarks
-			Because hardware gamma might not actually be supported, we need to 
-			ignore it sometimes. Because D3D doesn't encode sRGB in the format but
-			as a sampler state, and we don't want to change the original requested
-			hardware gamma flag (e.g. serialisation) we need another indicator.
-		*/
-		bool isHardwareGammaReadToBeUsed() const { return mHwGamma && mHwGammaReadSupported; }
-					
-		/// Will this texture need to be in the default pool?
-		bool useDefaultPool();
-
-		// Called immediately after the Direct3D device has been created.
-		virtual void notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device);
-
-		// Called before the Direct3D device is going to be destroyed.
-		virtual void notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device);
-
-		// Called immediately after the Direct3D device has entered a lost state.
-		virtual void notifyOnDeviceLost(IDirect3DDevice9* d3d9Device);
-
-		// Called immediately after the Direct3D device has been reset
-		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);	
     };
 
 	typedef std::shared_ptr<D3D9Texture> D3D9TexturePtr;

+ 0 - 10
CamelotD3D9Renderer/Source/CmD3D9GpuProgramManager.cpp

@@ -53,14 +53,4 @@ namespace CamelotEngine {
             return new D3D9GpuFragmentProgram();
         }
     }
-
-	GpuProgramPtr D3D9GpuProgramManager::createProgram(const String& code, GpuProgramType gptype, const String& syntaxCode)
-    {
-		GpuProgramPtr prg = GpuProgramPtr(create(gptype, syntaxCode));
-        // Set all prarmeters (create does not set, just determines factory)
-		prg->setType(gptype);
-		prg->setSyntaxCode(syntaxCode);
-		prg->setSource(code);
-        return prg;
-    }
 }

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp

@@ -64,7 +64,7 @@ namespace CamelotEngine {
 		return prog;
 	}
     //-----------------------------------------------------------------------
-	void D3D9HLSLProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void D3D9HLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
         delete prog;
     }

+ 0 - 21
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -196,14 +196,6 @@ namespace CamelotEngine
 
 		createInternalResources();
 
-		if (!mInternalResourcesCreated)
-		{
-			// NB: Need to initialise pool to some value other than D3DPOOL_DEFAULT,
-			// otherwise, if the texture loading failed, it might re-create as empty
-			// texture when device lost/restore. The actual pool will determine later.
-			mD3DPool = D3DPOOL_MANAGED;
-		}
-
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
 		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
@@ -219,12 +211,6 @@ namespace CamelotEngine
 
 		Resource::initialize_internal();
 	}
-	/****************************************************************************************/
-	void D3D9Texture::freeInternalResources(void)
-	{
-		freeInternalResourcesImpl();
-	}
-
 	/****************************************************************************************/
 	void D3D9Texture::freeInternalResourcesImpl()
 	{
@@ -309,13 +295,6 @@ namespace CamelotEngine
 
 		return instanceSize * mMapDeviceToTextureResources.size();
 	}
-
-	/****************************************************************************************/
-	void D3D9Texture::createInternalResources(void)
-	{
-		createInternalResourcesImpl();
-	}
-
 	/****************************************************************************************/
 	void D3D9Texture::determinePool()
 	{

+ 2 - 0
CamelotFBXImporter/Source/CmFBXImporter.cpp

@@ -52,6 +52,8 @@ namespace CamelotEngine
 		mesh.waitUntilLoaded();
 		mesh->setMeshData(meshData);
 
+		registerLoadedResource(mesh);
+
 		return mesh;
 	}
 

+ 2 - 0
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

@@ -149,6 +149,8 @@ namespace CamelotEngine
 
 		fileData->close();
 
+		registerLoadedResource(newTexture);
+
 		return newTexture;
 	}
 

+ 5 - 3
CamelotGLRenderer/Include/CmGLTexture.h

@@ -40,9 +40,6 @@ namespace CamelotEngine {
     class CM_RSGL_EXPORT GLTexture : public Texture
     {
     public:
-        // Constructor
-        GLTexture(GLSupport& support);
-
         virtual ~GLTexture();      
 
 		/// @copydoc Texture::getBuffer
@@ -56,6 +53,11 @@ namespace CamelotEngine {
 		void getCustomAttribute_internal(const String& name, void* pData);
 
     protected:
+		friend class GLTextureManager;
+
+		// Constructor
+		GLTexture(GLSupport& support);
+
 		void initialize_internal();
 
 		/// @copydoc Texture::createInternalResourcesImpl

+ 1 - 1
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgramFactory.h

@@ -48,7 +48,7 @@ namespace CamelotEngine
 		/// create an instance of GLSLProgram
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
-		void destroy(HighLevelGpuProgram* prog);
+		void destroy_internal(HighLevelGpuProgram* prog);
     };
 }
 

+ 1 - 1
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp

@@ -66,7 +66,7 @@ namespace CamelotEngine {
 		return prog;
 	}
     //-----------------------------------------------------------------------
-	void GLSLProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void GLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
         delete prog;
     }

+ 1 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -208,6 +208,7 @@
     <ClCompile Include="Source\CmResources.cpp" />
     <ClCompile Include="Source\CmSceneManager.cpp" />
     <ClCompile Include="Source\CmShader.cpp" />
+    <ClCompile Include="Source\CmSpecificImporter.cpp" />
     <ClCompile Include="Source\CmTechnique.cpp" />
     <ClCompile Include="Source\CmTexture.cpp" />
     <ClCompile Include="Source\CmTextureManager.cpp" />

+ 3 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -457,5 +457,8 @@
     <ClCompile Include="Source\CmResourceHandle.cpp">
       <Filter>Source Files\Resources</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmSpecificImporter.cpp">
+      <Filter>Source Files\Importer</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 1 - 1
CamelotRenderer/Include/CmCgProgramFactory.h

@@ -47,7 +47,7 @@ namespace CamelotEngine
 		const String& getLanguage(void) const;
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
-		void destroy(HighLevelGpuProgram* prog);
+		void destroy_internal(HighLevelGpuProgram* prog);
 
     };
 }

+ 17 - 0
CamelotRenderer/Include/CmGpuProgram.h

@@ -213,6 +213,8 @@ namespace CamelotEngine {
 
 
     protected:
+		friend class GpuProgramManager;
+
         /// Virtual method which must be implemented by subclasses, load from mSource
         virtual void loadFromSource(void) = 0;
 
@@ -223,6 +225,21 @@ namespace CamelotEngine {
 		friend class GpuProgramRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
+
+	/************************************************************************/
+	/* 								STATICS		                     		*/
+	/************************************************************************/
+	private:
+		/**
+		 * @brief	Schedules destruction of the provided object. Actual destruction happens on the
+		 * 			render thread.
+		 */
+		static void destruct(GpuProgram* ptr);
+
+		/**
+		 * @brief	Destroys the provided object. Should only be called on the render thread.
+		 */
+		static void destruct_internal(GpuProgram* ptr);
 	};
 
 	/** @} */

+ 1 - 1
CamelotRenderer/Include/CmGpuProgramManager.h

@@ -106,7 +106,7 @@ namespace CamelotEngine {
 		@param gptype The type of program to create.
         @param syntaxCode The name of the syntax to be used for this program e.g. arbvp1, vs_1_1
 		*/
-		virtual GpuProgramPtr createProgram(const String& code, 
+		GpuProgramPtr createProgram(const String& code, 
             GpuProgramType gptype, const String& syntaxCode);
 	};
 

+ 3 - 1
CamelotRenderer/Include/CmHighLevelGpuProgramManager.h

@@ -51,7 +51,9 @@ namespace CamelotEngine {
 		virtual const String& getLanguage(void) const = 0;
         virtual HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile) = 0;
 		virtual HighLevelGpuProgram* create() = 0;
-		virtual void destroy(HighLevelGpuProgram* prog) = 0;
+
+		void destroy(HighLevelGpuProgram* prog);
+		virtual void destroy_internal(HighLevelGpuProgram* prog) = 0;
 	};
 	/** This ResourceManager manages high-level vertex and fragment programs. 
 	@remarks

+ 10 - 2
CamelotRenderer/Include/CmMesh.h

@@ -61,11 +61,19 @@ namespace CamelotEngine
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 
-		static MeshPtr createEmpty();
-
 		/************************************************************************/
 		/* 								STATICS		                     		*/
 		/************************************************************************/
+	private:
+		static MeshPtr createEmpty();
+
+		/**
+		 * @brief	Returns empty mesh data. (Technically it is not empty,
+		 * 			as 0 sized buffers will cause problems, so it contains 3 indices
+		 * 			and 1 vertex).
+		 */
+		static MeshDataPtr getNullMeshData();
+		
 	public:
 		static MeshPtr create();
 	};

+ 5 - 0
CamelotRenderer/Include/CmResourceHandle.h

@@ -41,6 +41,11 @@ namespace CamelotEngine
 		 */
 		void waitUntilLoaded() const;
 
+		/**
+		 * @brief	Returns the UUID of the resource the handle is referring to.
+		 */
+		const String& getUUID() const { return mData->mUUID; }
+
 	protected:
 		ResourceHandleBase();
 

+ 9 - 1
CamelotRenderer/Include/CmResources.h

@@ -143,7 +143,7 @@ namespace CamelotEngine
 		WorkQueuePtr mWorkQueue; // TODO Low priority - I might want to make this more global so other classes can use it
 		UINT16 mWorkQueueChannel;
 
-		unordered_map<String, BaseResourceHandle>::type mLoadedResources; // TODO Low priority - I'm not sure how will filePath as key do performance wise
+		unordered_map<String, BaseResourceHandle>::type mLoadedResources; // TODO Low priority - I'm not sure how will UUID (a string) do as key do performance wise
 		unordered_map<String, ResourceAsyncOp>::type mInProgressResources; // Resources that are being asynchronously loaded
 
 		BaseResourceHandle loadInternal(const String& filePath, bool synchronous); 
@@ -164,6 +164,14 @@ namespace CamelotEngine
 		const String& getUUIDFromPath(const String& path) const;
 
 		String mMetaDataFolderPath;
+
+	private:
+		friend class SpecificImporter;
+
+		/**
+		 * @brief	Registers the newly loaded resource in the global Resources library.
+		 */
+		void registerLoadedResource(BaseResourceHandle resource);
 	};
 
 	CM_EXPORT Resources& gResources();

+ 6 - 0
CamelotRenderer/Include/CmSpecificImporter.h

@@ -29,5 +29,11 @@ namespace CamelotEngine
 		 * @return	null if it fails, otherwise the loaded object.
 		 */
 		virtual BaseResourceHandle import(const String& filePath) = 0;
+
+	protected:
+		/**
+		 * @brief	Registers the newly loaded resource in the global Resources library.
+		 */
+		void registerLoadedResource(BaseResourceHandle resource);
 	};
 }

+ 12 - 5
CamelotRenderer/Include/CmTexture.h

@@ -94,8 +94,6 @@ namespace CamelotEngine {
     class CM_EXPORT Texture : public Resource
     {
     public:
-        Texture();
-
         /** Gets the type of texture 
         */
         virtual TextureType getTextureType(void) const { return mTextureType; }
@@ -241,9 +239,7 @@ namespace CamelotEngine {
 		PixelFormat mFormat;
         int mUsage; // Bit field, so this can't be TextureUsage
 
-		bool mInternalResourcesCreated;
-
-		protected:
+		Texture();
 
 		/**
 		 * @brief	Initializes the texture. This must be called right after the texture is constructed. Called by TextureManager
@@ -311,6 +307,17 @@ namespace CamelotEngine {
 		static TexturePtr create(TextureType texType, UINT32 width, UINT32 height, int num_mips,
 			PixelFormat format, int usage = TU_DEFAULT,
 			bool hwGammaCorrection = false, UINT32 fsaa = 0, const String& fsaaHint = StringUtil::BLANK);
+
+	private:
+		/**
+		 * @brief	Schedules destruction of the provided object. Actual destruction happens on the render thread.
+		 */
+		static void destruct(Texture* ptr);
+
+		/**
+		 * @brief	Destroys the provided object. Should only be called on the render thread.
+		 */
+		static void destruct_internal(Texture* ptr);
     };
 
 	/** @} */

+ 1 - 1
CamelotRenderer/Source/CmCgProgramFactory.cpp

@@ -71,7 +71,7 @@ namespace CamelotEngine {
 		return prog;
 	}
     //-----------------------------------------------------------------------
-	void CgProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void CgProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
         delete prog;
     }

+ 13 - 0
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -184,6 +184,19 @@ namespace CamelotEngine
 	{
 		return GpuProgram::getRTTIStatic();
 	}
+
+	/************************************************************************/
+	/* 								STATICS		                     		*/
+	/************************************************************************/
+	void GpuProgram::destruct(GpuProgram* ptr)
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&GpuProgram::destruct_internal, ptr));
+	}
+
+	void GpuProgram::destruct_internal(GpuProgram* ptr)
+	{
+		delete ptr;
+	}
 }
 
 #undef THROW_IF_NOT_RENDER_THREAD 

+ 1 - 1
CamelotRenderer/Source/CmGpuProgramManager.cpp

@@ -57,7 +57,7 @@ namespace CamelotEngine {
 	GpuProgramPtr GpuProgramManager::createProgram(const String& code, GpuProgramType gptype, 
 		const String& syntaxCode)
     {
-		GpuProgramPtr prg = GpuProgramPtr(create(gptype, syntaxCode));
+		GpuProgramPtr prg = GpuProgramPtr(create(gptype, syntaxCode), &GpuProgram::destruct);
         // Set all prarmeters (create does not set, just determines factory)
 		prg->setType(gptype);
 		prg->setSyntaxCode(syntaxCode);

+ 14 - 4
CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp

@@ -26,6 +26,8 @@ THE SOFTWARE.
 -----------------------------------------------------------------------------
 */
 #include "CmHighLevelGpuProgramManager.h"
+#include "CmRenderSystemManager.h"
+#include "CmRenderSystem.h"
 
 namespace CamelotEngine {
 
@@ -90,7 +92,7 @@ namespace CamelotEngine {
 			return new NullProgram();
 		}
 
-		void destroy(HighLevelGpuProgram* prog)
+		void destroy_internal(HighLevelGpuProgram* prog)
 		{
 			delete prog;
 		}
@@ -136,6 +138,11 @@ namespace CamelotEngine {
 		}
 		return i->second;
 	}
+	//---------------------------------------------------------------------------
+	void HighLevelGpuProgramFactory::destroy(HighLevelGpuProgram* prog)
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&HighLevelGpuProgramFactory::destroy_internal, this, prog));
+	}
 	//---------------------------------------------------------------------
 	bool HighLevelGpuProgramManager::isLanguageSupported(const String& lang)
 	{
@@ -147,7 +154,8 @@ namespace CamelotEngine {
     //---------------------------------------------------------------------------
     HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile)
     {
-        HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create(source, entryPoint, profile));
+		HighLevelGpuProgramFactory* factory = getFactory(language);
+        HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(source, entryPoint, profile), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
 
         HighLevelGpuProgramPtr prg = ret;
         prg->setType(gptype);
@@ -159,7 +167,8 @@ namespace CamelotEngine {
 	//---------------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& language)
 	{
-		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create());
+		HighLevelGpuProgramFactory* factory = getFactory(language);
+		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
 		ret->initialize();
 
 		return ret;
@@ -167,7 +176,8 @@ namespace CamelotEngine {
 	//---------------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::createEmpty(const String& language)
 	{
-		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(getFactory(language)->create());
+		HighLevelGpuProgramFactory* factory = getFactory(language);
+		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
 
 		return ret;
 	}

+ 33 - 2
CamelotRenderer/Source/CmMesh.cpp

@@ -308,8 +308,7 @@ namespace CamelotEngine
 		// TODO Low priority - Initialize an empty mesh. A better way would be to only initialize the mesh
 		// once we set the proper mesh data (then we don't have to do it twice), but this makes the code less complex.
 		// Consider changing it if there are performance issues.
-		MeshDataPtr meshData = MeshDataPtr(new MeshData());
-		setMeshData_internal(meshData);
+		setMeshData_internal(getNullMeshData());
 
 		Resource::initialize_internal();
 	}
@@ -352,6 +351,38 @@ namespace CamelotEngine
 
 		return mesh;
 	}
+
+	MeshDataPtr Mesh::getNullMeshData()
+	{
+		static MeshDataPtr NULL_MESH_DATA = nullptr;
+
+		if(NULL_MESH_DATA == nullptr)
+		{
+			NULL_MESH_DATA = MeshDataPtr(new MeshData());
+
+			NULL_MESH_DATA->indexCount = 3;
+			NULL_MESH_DATA->vertexCount = 1;
+
+			NULL_MESH_DATA->index = new int[3];
+			NULL_MESH_DATA->index[0] = 0;
+			NULL_MESH_DATA->index[1] = 0;
+			NULL_MESH_DATA->index[2] = 0;
+
+			std::shared_ptr<MeshData::VertexData> vertexData = std::shared_ptr<MeshData::VertexData>(new MeshData::VertexData(1));
+			NULL_MESH_DATA->vertexBuffers.insert(std::make_pair(0, vertexData));
+			vertexData->vertex = new Vector3[1];
+			vertexData->vertex[0] = Vector3(0, 0, 0);
+
+			NULL_MESH_DATA->declaration->addElement(0, 0, VET_FLOAT3, VES_POSITION);
+
+			MeshData::SubMeshData subMesh;
+			subMesh.indexOffset = 0;
+			subMesh.indexCount = 3;
+			NULL_MESH_DATA->subMeshes.push_back(subMesh);
+		}
+
+		return NULL_MESH_DATA;
+	}
 }
 
 #undef THROW_IF_NOT_RENDER_THREAD

+ 30 - 16
CamelotRenderer/Source/CmResources.cpp

@@ -34,7 +34,7 @@ namespace CamelotEngine
 	{
 		ResourceLoadRequestPtr resRequest = boost::any_cast<ResourceLoadRequestPtr>(res->getRequest()->getData());
 
-		auto iterFind = gResources().mInProgressResources.find(resRequest->filePath);
+		auto iterFind = gResources().mInProgressResources.find(resRequest->resource.getUUID());
 		gResources().mInProgressResources.erase(iterFind);
 
 		if(res->getRequest()->getAborted())
@@ -52,7 +52,7 @@ namespace CamelotEngine
 				gResources().addMetaData(resResponse->rawResource->getUUID(), resRequest->filePath);
 			}
 
-			gResources().mLoadedResources[resRequest->filePath] = resRequest->resource;
+			gResources().mLoadedResources[resResponse->rawResource->getUUID()] = resRequest->resource;
 		}
 		else
 		{
@@ -150,13 +150,25 @@ namespace CamelotEngine
 
 	BaseResourceHandle Resources::loadInternal(const String& filePath, bool synchronous)
 	{
-		auto iterFind = mLoadedResources.find(filePath);
+		// TODO Low priority - Right now I don't allow loading of resources that don't have meta-data, because I need to know resources UUID
+		// at this point. And I can't do that without having meta-data. Other option is to partially load the resource to read the UUID but due to the
+		// nature of the serializer it could complicate things. (But possible if this approach proves troublesome)
+		// The reason I need the UUID is that when resource is loaded Async, the returned ResourceHandle needs to have a valid UUID, in case I assign that
+		// ResourceHandle to something and then save that something. If I didn't assign it, the saved ResourceHandle would have a blank (i.e. invalid) UUID.
+		if(!metaExists_Path(filePath))
+		{
+			CM_EXCEPT(InternalErrorException, "Cannot load resource that isn't registered in the meta database. Call Resources::create first.");
+		}
+
+		String uuid = getUUIDFromPath(filePath);
+
+		auto iterFind = mLoadedResources.find(uuid);
 		if(iterFind != mLoadedResources.end()) // Resource is already loaded
 		{
 			return iterFind->second;
 		}
 
-		auto iterFind2 = mInProgressResources.find(filePath);
+		auto iterFind2 = mInProgressResources.find(uuid);
 		if(iterFind2 != mInProgressResources.end()) // We're already loading this resource
 		{
 			ResourceAsyncOp& asyncOp = iterFind2->second;
@@ -177,17 +189,6 @@ namespace CamelotEngine
 			return nullptr;
 		}
 
-		// TODO Low priority - Right now I don't allow loading of resources that don't have meta-data, because I need to know resources UUID
-		// at this point. And I can't do that without having meta-data. Other option is to partially load the resource to read the UUID but due to the
-		// nature of the serializer it could complicate things. (But possible if this approach proves troublesome)
-		// The reason I need the UUID is that when resource is loaded Async, the returned ResourceHandle needs to have a valid UUID, in case I assign that
-		// ResourceHandle to something and then save that something. If I didn't assign it, the saved ResourceHandle would have a blank (i.e. invalid) UUID.
-		if(!metaExists_Path(filePath))
-		{
-			CM_EXCEPT(InternalErrorException, "Cannot load resource that isn't registered in the meta database. Call Resources::create first.");
-		}
-
-		String uuid = getUUIDFromPath(filePath);
 		BaseResourceHandle newResource;
 		newResource.setUUID(uuid); // UUID needs to be set immediately if the resource gets loaded async
 
@@ -200,7 +201,7 @@ namespace CamelotEngine
 		newAsyncOp.resource = newResource;
 		newAsyncOp.requestID = requestId;
 
-		mInProgressResources[filePath] = newAsyncOp;
+		mInProgressResources[uuid] = newAsyncOp;
 
 		mWorkQueue->addRequest(mWorkQueueChannel, resRequest, 0, synchronous);
 		return newResource;
@@ -262,6 +263,19 @@ namespace CamelotEngine
 		fs.encode(resource.get(), filePath);
 	}
 
+	void Resources::registerLoadedResource(BaseResourceHandle resource)
+	{
+		auto iterFind = mLoadedResources.find(resource->getUUID());
+		if(iterFind == mLoadedResources.end())
+		{
+			mLoadedResources.insert(std::make_pair(resource->getUUID(), resource));
+		}
+		else
+		{
+			LOGDBG("Resource with the same UUID (" + resource->getUUID() + ") already exists!");
+		}
+	}
+
 	void Resources::loadMetaData()
 	{
 		vector<String>::type allFiles = FileSystem::getFiles(mMetaDataFolderPath);

+ 10 - 0
CamelotRenderer/Source/CmSpecificImporter.cpp

@@ -0,0 +1,10 @@
+#include "CmSpecificImporter.h"
+#include "CmResources.h"
+
+namespace CamelotEngine
+{
+	void SpecificImporter::registerLoadedResource(BaseResourceHandle resource)
+	{
+		gResources().instance().registerLoadedResource(resource);
+	}
+}

+ 13 - 12
CamelotRenderer/Source/CmTexture.cpp

@@ -53,8 +53,7 @@ namespace CamelotEngine {
 			mFSAA(0),
             mTextureType(TEX_TYPE_2D),            
             mFormat(PF_UNKNOWN),
-            mUsage(TU_DEFAULT),
-            mInternalResourcesCreated(false)
+            mUsage(TU_DEFAULT)
     {
         
     }
@@ -100,20 +99,12 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
 	void Texture::createInternalResources(void)
 	{
-		if (!mInternalResourcesCreated)
-		{
-			createInternalResourcesImpl();
-			mInternalResourcesCreated = true;
-		}
+		createInternalResourcesImpl();
 	}
 	//-----------------------------------------------------------------------------
 	void Texture::freeInternalResources(void)
 	{
-		if (mInternalResourcesCreated)
-		{
-			freeInternalResourcesImpl();
-			mInternalResourcesCreated = false;
-		}
+		freeInternalResourcesImpl();
 	}
 
 	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
@@ -259,6 +250,16 @@ namespace CamelotEngine {
 		return TextureManager::instance().create(texType, 
 			width, height, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 	}
+
+	void Texture::destruct(Texture* ptr)
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&Texture::destruct_internal, ptr));
+	}
+
+	void Texture::destruct_internal(Texture* ptr)
+	{
+		delete ptr;
+	}
 }
 
 #undef THROW_IF_NOT_RENDER_THREAD

+ 2 - 2
CamelotRenderer/Source/CmTextureManager.cpp

@@ -45,7 +45,7 @@ namespace CamelotEngine {
         PixelFormat format, int usage, bool hwGamma, 
 		UINT32 fsaa, const String& fsaaHint)
     {
-        TexturePtr ret = TexturePtr(createImpl());
+        TexturePtr ret = TexturePtr(createImpl(), &Texture::destruct);
 		ret->initialize(texType, width, height, depth, static_cast<size_t>(numMipmaps), format, usage, hwGamma, fsaa, fsaaHint);
 
 		return ret;
@@ -53,7 +53,7 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------
 	TexturePtr TextureManager::createEmpty()
 	{
-		TexturePtr ret = TexturePtr(createImpl());
+		TexturePtr ret = TexturePtr(createImpl(), &Texture::destruct);
 
 		return ret;
 	}