瀏覽代碼

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
     class CM_D3D9_EXPORT D3D9GpuProgramManager : public GpuProgramManager
     {
     {
-    public:
-		GpuProgramPtr createProgram(const String& code, GpuProgramType gptype, const String& syntaxCode);
     public:
     public:
         D3D9GpuProgramManager();
         D3D9GpuProgramManager();
 		~D3D9GpuProgramManager();
 		~D3D9GpuProgramManager();

+ 1 - 1
CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h

@@ -45,7 +45,7 @@ namespace CamelotEngine
 		const String& getLanguage(void) const;
 		const String& getLanguage(void) const;
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
 		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 {
 namespace CamelotEngine {
 	class CM_D3D9_EXPORT D3D9Texture : public Texture, public D3D9Resource
 	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:	
 	protected:	
+		friend class D3D9TextureManager;
+		friend class D3D9HardwarePixelBuffer;
 
 
 		struct TextureResources
 		struct TextureResources
 		{
 		{
@@ -60,7 +103,6 @@ namespace CamelotEngine {
 		/// Map between device to texture resources.
 		/// Map between device to texture resources.
 		DeviceToTextureResourcesMap	mMapDeviceToTextureResources;
 		DeviceToTextureResourcesMap	mMapDeviceToTextureResources;
 
 
-
 		/// Vector of pointers to subsurfaces
 		/// Vector of pointers to subsurfaces
 		typedef vector<HardwarePixelBufferPtr>::type SurfaceList;
 		typedef vector<HardwarePixelBufferPtr>::type SurfaceList;
 		SurfaceList	mSurfaceList;
 		SurfaceList	mSurfaceList;
@@ -78,6 +120,8 @@ namespace CamelotEngine {
 		D3DMULTISAMPLE_TYPE mFSAAType;
 		D3DMULTISAMPLE_TYPE mFSAAType;
 		DWORD mFSAAQuality;
 		DWORD mFSAAQuality;
 
 
+		D3D9Texture();
+
 		/// overriden from Resource
 		/// overriden from Resource
 		void initialize_internal();	
 		void initialize_internal();	
 
 
@@ -93,10 +137,6 @@ namespace CamelotEngine {
 
 
 		/// @copydoc Resource::calculateSize
 		/// @copydoc Resource::calculateSize
 		size_t calculateSize(void) const;
 		size_t calculateSize(void) const;
-		/// @copydoc Texture::createInternalResources
-		void createInternalResources(void);
-		/// @copydoc Texture::freeInternalResources
-		void freeInternalResources(void);
 		/// @copydoc Texture::createInternalResourcesImpl
 		/// @copydoc Texture::createInternalResourcesImpl
 		void createInternalResourcesImpl(void);
 		void createInternalResourcesImpl(void);
 		/// Creates this texture resources on the specified device.
 		/// Creates this texture resources on the specified device.
@@ -136,50 +176,6 @@ namespace CamelotEngine {
 		void freeTextureResources(IDirect3DDevice9* d3d9Device, TextureResources* textureResources);
 		void freeTextureResources(IDirect3DDevice9* d3d9Device, TextureResources* textureResources);
 
 
 		void determinePool();
 		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;
 	typedef std::shared_ptr<D3D9Texture> D3D9TexturePtr;

+ 0 - 10
CamelotD3D9Renderer/Source/CmD3D9GpuProgramManager.cpp

@@ -53,14 +53,4 @@ namespace CamelotEngine {
             return new D3D9GpuFragmentProgram();
             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;
 		return prog;
 	}
 	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-	void D3D9HLSLProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void D3D9HLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
     {
         delete prog;
         delete prog;
     }
     }

+ 0 - 21
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -196,14 +196,6 @@ namespace CamelotEngine
 
 
 		createInternalResources();
 		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
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
 
 		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
 		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
@@ -219,12 +211,6 @@ namespace CamelotEngine
 
 
 		Resource::initialize_internal();
 		Resource::initialize_internal();
 	}
 	}
-	/****************************************************************************************/
-	void D3D9Texture::freeInternalResources(void)
-	{
-		freeInternalResourcesImpl();
-	}
-
 	/****************************************************************************************/
 	/****************************************************************************************/
 	void D3D9Texture::freeInternalResourcesImpl()
 	void D3D9Texture::freeInternalResourcesImpl()
 	{
 	{
@@ -309,13 +295,6 @@ namespace CamelotEngine
 
 
 		return instanceSize * mMapDeviceToTextureResources.size();
 		return instanceSize * mMapDeviceToTextureResources.size();
 	}
 	}
-
-	/****************************************************************************************/
-	void D3D9Texture::createInternalResources(void)
-	{
-		createInternalResourcesImpl();
-	}
-
 	/****************************************************************************************/
 	/****************************************************************************************/
 	void D3D9Texture::determinePool()
 	void D3D9Texture::determinePool()
 	{
 	{

+ 2 - 0
CamelotFBXImporter/Source/CmFBXImporter.cpp

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

+ 2 - 0
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

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

+ 5 - 3
CamelotGLRenderer/Include/CmGLTexture.h

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

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

@@ -48,7 +48,7 @@ namespace CamelotEngine
 		/// create an instance of GLSLProgram
 		/// create an instance of GLSLProgram
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
         HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
 		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;
 		return prog;
 	}
 	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-	void GLSLProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void GLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
     {
         delete prog;
         delete prog;
     }
     }

+ 1 - 0
CamelotRenderer/CamelotRenderer.vcxproj

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

+ 3 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

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

+ 1 - 1
CamelotRenderer/Include/CmCgProgramFactory.h

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

+ 17 - 0
CamelotRenderer/Include/CmGpuProgram.h

@@ -213,6 +213,8 @@ namespace CamelotEngine {
 
 
 
 
     protected:
     protected:
+		friend class GpuProgramManager;
+
         /// Virtual method which must be implemented by subclasses, load from mSource
         /// Virtual method which must be implemented by subclasses, load from mSource
         virtual void loadFromSource(void) = 0;
         virtual void loadFromSource(void) = 0;
 
 
@@ -223,6 +225,21 @@ namespace CamelotEngine {
 		friend class GpuProgramRTTI;
 		friend class GpuProgramRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 		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 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
         @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);
             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 const String& getLanguage(void) const = 0;
         virtual HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile) = 0;
         virtual HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramProfile profile) = 0;
 		virtual HighLevelGpuProgram* create() = 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. 
 	/** This ResourceManager manages high-level vertex and fragment programs. 
 	@remarks
 	@remarks

+ 10 - 2
CamelotRenderer/Include/CmMesh.h

@@ -61,11 +61,19 @@ namespace CamelotEngine
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
 		virtual RTTITypeBase* getRTTI() const;
 		virtual RTTITypeBase* getRTTI() const;
 
 
-		static MeshPtr createEmpty();
-
 		/************************************************************************/
 		/************************************************************************/
 		/* 								STATICS		                     		*/
 		/* 								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:
 	public:
 		static MeshPtr create();
 		static MeshPtr create();
 	};
 	};

+ 5 - 0
CamelotRenderer/Include/CmResourceHandle.h

@@ -41,6 +41,11 @@ namespace CamelotEngine
 		 */
 		 */
 		void waitUntilLoaded() const;
 		void waitUntilLoaded() const;
 
 
+		/**
+		 * @brief	Returns the UUID of the resource the handle is referring to.
+		 */
+		const String& getUUID() const { return mData->mUUID; }
+
 	protected:
 	protected:
 		ResourceHandleBase();
 		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
 		WorkQueuePtr mWorkQueue; // TODO Low priority - I might want to make this more global so other classes can use it
 		UINT16 mWorkQueueChannel;
 		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
 		unordered_map<String, ResourceAsyncOp>::type mInProgressResources; // Resources that are being asynchronously loaded
 
 
 		BaseResourceHandle loadInternal(const String& filePath, bool synchronous); 
 		BaseResourceHandle loadInternal(const String& filePath, bool synchronous); 
@@ -164,6 +164,14 @@ namespace CamelotEngine
 		const String& getUUIDFromPath(const String& path) const;
 		const String& getUUIDFromPath(const String& path) const;
 
 
 		String mMetaDataFolderPath;
 		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();
 	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.
 		 * @return	null if it fails, otherwise the loaded object.
 		 */
 		 */
 		virtual BaseResourceHandle import(const String& filePath) = 0;
 		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
     class CM_EXPORT Texture : public Resource
     {
     {
     public:
     public:
-        Texture();
-
         /** Gets the type of texture 
         /** Gets the type of texture 
         */
         */
         virtual TextureType getTextureType(void) const { return mTextureType; }
         virtual TextureType getTextureType(void) const { return mTextureType; }
@@ -241,9 +239,7 @@ namespace CamelotEngine {
 		PixelFormat mFormat;
 		PixelFormat mFormat;
         int mUsage; // Bit field, so this can't be TextureUsage
         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
 		 * @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,
 		static TexturePtr create(TextureType texType, UINT32 width, UINT32 height, int num_mips,
 			PixelFormat format, int usage = TU_DEFAULT,
 			PixelFormat format, int usage = TU_DEFAULT,
 			bool hwGammaCorrection = false, UINT32 fsaa = 0, const String& fsaaHint = StringUtil::BLANK);
 			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;
 		return prog;
 	}
 	}
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
-	void CgProgramFactory::destroy(HighLevelGpuProgram* prog)
+	void CgProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
     {
     {
         delete prog;
         delete prog;
     }
     }

+ 13 - 0
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -184,6 +184,19 @@ namespace CamelotEngine
 	{
 	{
 		return GpuProgram::getRTTIStatic();
 		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 
 #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, 
 	GpuProgramPtr GpuProgramManager::createProgram(const String& code, GpuProgramType gptype, 
 		const String& syntaxCode)
 		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)
         // Set all prarmeters (create does not set, just determines factory)
 		prg->setType(gptype);
 		prg->setType(gptype);
 		prg->setSyntaxCode(syntaxCode);
 		prg->setSyntaxCode(syntaxCode);

+ 14 - 4
CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp

@@ -26,6 +26,8 @@ THE SOFTWARE.
 -----------------------------------------------------------------------------
 -----------------------------------------------------------------------------
 */
 */
 #include "CmHighLevelGpuProgramManager.h"
 #include "CmHighLevelGpuProgramManager.h"
+#include "CmRenderSystemManager.h"
+#include "CmRenderSystem.h"
 
 
 namespace CamelotEngine {
 namespace CamelotEngine {
 
 
@@ -90,7 +92,7 @@ namespace CamelotEngine {
 			return new NullProgram();
 			return new NullProgram();
 		}
 		}
 
 
-		void destroy(HighLevelGpuProgram* prog)
+		void destroy_internal(HighLevelGpuProgram* prog)
 		{
 		{
 			delete prog;
 			delete prog;
 		}
 		}
@@ -136,6 +138,11 @@ namespace CamelotEngine {
 		}
 		}
 		return i->second;
 		return i->second;
 	}
 	}
+	//---------------------------------------------------------------------------
+	void HighLevelGpuProgramFactory::destroy(HighLevelGpuProgram* prog)
+	{
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&HighLevelGpuProgramFactory::destroy_internal, this, prog));
+	}
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
 	bool HighLevelGpuProgramManager::isLanguageSupported(const String& lang)
 	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 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;
         HighLevelGpuProgramPtr prg = ret;
         prg->setType(gptype);
         prg->setType(gptype);
@@ -159,7 +167,8 @@ namespace CamelotEngine {
 	//---------------------------------------------------------------------------
 	//---------------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& language)
 	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();
 		ret->initialize();
 
 
 		return ret;
 		return ret;
@@ -167,7 +176,8 @@ namespace CamelotEngine {
 	//---------------------------------------------------------------------------
 	//---------------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::createEmpty(const String& language)
 	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;
 		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
 		// 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.
 		// 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.
 		// Consider changing it if there are performance issues.
-		MeshDataPtr meshData = MeshDataPtr(new MeshData());
-		setMeshData_internal(meshData);
+		setMeshData_internal(getNullMeshData());
 
 
 		Resource::initialize_internal();
 		Resource::initialize_internal();
 	}
 	}
@@ -352,6 +351,38 @@ namespace CamelotEngine
 
 
 		return mesh;
 		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
 #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());
 		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);
 		gResources().mInProgressResources.erase(iterFind);
 
 
 		if(res->getRequest()->getAborted())
 		if(res->getRequest()->getAborted())
@@ -52,7 +52,7 @@ namespace CamelotEngine
 				gResources().addMetaData(resResponse->rawResource->getUUID(), resRequest->filePath);
 				gResources().addMetaData(resResponse->rawResource->getUUID(), resRequest->filePath);
 			}
 			}
 
 
-			gResources().mLoadedResources[resRequest->filePath] = resRequest->resource;
+			gResources().mLoadedResources[resResponse->rawResource->getUUID()] = resRequest->resource;
 		}
 		}
 		else
 		else
 		{
 		{
@@ -150,13 +150,25 @@ namespace CamelotEngine
 
 
 	BaseResourceHandle Resources::loadInternal(const String& filePath, bool synchronous)
 	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
 		if(iterFind != mLoadedResources.end()) // Resource is already loaded
 		{
 		{
 			return iterFind->second;
 			return iterFind->second;
 		}
 		}
 
 
-		auto iterFind2 = mInProgressResources.find(filePath);
+		auto iterFind2 = mInProgressResources.find(uuid);
 		if(iterFind2 != mInProgressResources.end()) // We're already loading this resource
 		if(iterFind2 != mInProgressResources.end()) // We're already loading this resource
 		{
 		{
 			ResourceAsyncOp& asyncOp = iterFind2->second;
 			ResourceAsyncOp& asyncOp = iterFind2->second;
@@ -177,17 +189,6 @@ namespace CamelotEngine
 			return nullptr;
 			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;
 		BaseResourceHandle newResource;
 		newResource.setUUID(uuid); // UUID needs to be set immediately if the resource gets loaded async
 		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.resource = newResource;
 		newAsyncOp.requestID = requestId;
 		newAsyncOp.requestID = requestId;
 
 
-		mInProgressResources[filePath] = newAsyncOp;
+		mInProgressResources[uuid] = newAsyncOp;
 
 
 		mWorkQueue->addRequest(mWorkQueueChannel, resRequest, 0, synchronous);
 		mWorkQueue->addRequest(mWorkQueueChannel, resRequest, 0, synchronous);
 		return newResource;
 		return newResource;
@@ -262,6 +263,19 @@ namespace CamelotEngine
 		fs.encode(resource.get(), filePath);
 		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()
 	void Resources::loadMetaData()
 	{
 	{
 		vector<String>::type allFiles = FileSystem::getFiles(mMetaDataFolderPath);
 		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),
 			mFSAA(0),
             mTextureType(TEX_TYPE_2D),            
             mTextureType(TEX_TYPE_2D),            
             mFormat(PF_UNKNOWN),
             mFormat(PF_UNKNOWN),
-            mUsage(TU_DEFAULT),
-            mInternalResourcesCreated(false)
+            mUsage(TU_DEFAULT)
     {
     {
         
         
     }
     }
@@ -100,20 +99,12 @@ namespace CamelotEngine {
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	void Texture::createInternalResources(void)
 	void Texture::createInternalResources(void)
 	{
 	{
-		if (!mInternalResourcesCreated)
-		{
-			createInternalResourcesImpl();
-			mInternalResourcesCreated = true;
-		}
+		createInternalResourcesImpl();
 	}
 	}
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	void Texture::freeInternalResources(void)
 	void Texture::freeInternalResources(void)
 	{
 	{
-		if (mInternalResourcesCreated)
-		{
-			freeInternalResourcesImpl();
-			mInternalResourcesCreated = false;
-		}
+		freeInternalResourcesImpl();
 	}
 	}
 
 
 	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
 	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
@@ -259,6 +250,16 @@ namespace CamelotEngine {
 		return TextureManager::instance().create(texType, 
 		return TextureManager::instance().create(texType, 
 			width, height, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 			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
 #undef THROW_IF_NOT_RENDER_THREAD

+ 2 - 2
CamelotRenderer/Source/CmTextureManager.cpp

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