ソースを参照

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

Marko Pintera 13 年 前
コミット
9d0b41f349
31 ファイル変更243 行追加138 行削除
  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;
 	}