Просмотр исходного кода

Refactored Textures and GpuPrograms so they use destroy() for releasing resources

Marko Pintera 13 лет назад
Родитель
Сommit
6b1f26b8ff
32 измененных файлов с 445 добавлено и 448 удалено
  1. 24 6
      CamelotD3D11RenderSystem/Include/CmD3D11GpuProgram.h
  2. 2 2
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h
  3. 2 7
      CamelotD3D11RenderSystem/Include/CmD3D11Texture.h
  4. 25 27
      CamelotD3D11RenderSystem/Source/CmD3D11GpuProgram.cpp
  5. 4 2
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp
  6. 29 32
      CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp
  7. 15 6
      CamelotD3D9Renderer/Include/CmD3D9GpuProgram.h
  8. 3 2
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgram.h
  9. 3 5
      CamelotD3D9Renderer/Include/CmD3D9Texture.h
  10. 11 7
      CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp
  11. 15 18
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp
  12. 40 53
      CamelotD3D9Renderer/Source/CmD3D9Texture.cpp
  13. 1 7
      CamelotGLRenderer/Include/CmGLTexture.h
  14. 91 104
      CamelotGLRenderer/Source/CmGLTexture.cpp
  15. 10 2
      CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h
  16. 2 2
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h
  17. 6 3
      CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp
  18. 7 7
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp
  19. 39 49
      CamelotRenderer/Include/CmGpuProgram.h
  20. 5 5
      CamelotRenderer/Include/CmHighLevelGpuProgram.h
  21. 18 5
      CamelotRenderer/Include/CmResource.h
  22. 1 41
      CamelotRenderer/Include/CmTexture.h
  23. 3 3
      CamelotRenderer/Source/CmCgProgram.cpp
  24. 8 21
      CamelotRenderer/Source/CmGpuProgram.cpp
  25. 7 9
      CamelotRenderer/Source/CmHighLevelGpuProgram.cpp
  26. 8 0
      CamelotRenderer/Source/CmResource.cpp
  27. 0 23
      CamelotRenderer/Source/CmTexture.cpp
  28. 11 0
      CamelotRenderer/TODO.txt
  29. 2 0
      CamelotUtility/CamelotUtility.vcxproj
  30. 6 0
      CamelotUtility/CamelotUtility.vcxproj.filters
  31. 25 0
      CamelotUtility/Include/CmIDestroyable.h
  32. 22 0
      CamelotUtility/Source/CmIDestroyable.cpp

+ 24 - 6
CamelotD3D11RenderSystem/Include/CmD3D11GpuProgram.h

@@ -36,7 +36,10 @@ namespace CamelotEngine
 		ID3D11VertexShader* getVertexShader(void) const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 
 	class CM_D3D11_EXPORT D3D11GpuFragmentProgram : public D3D11GpuProgram
@@ -50,7 +53,10 @@ namespace CamelotEngine
 		ID3D11PixelShader* getPixelShader(void) const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 
 	class D3D11GpuDomainProgram : public D3D11GpuProgram
@@ -64,7 +70,10 @@ namespace CamelotEngine
 		ID3D11DomainShader* getDomainShader(void) const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 
 	class D3D11GpuHullProgram : public D3D11GpuProgram
@@ -78,7 +87,10 @@ namespace CamelotEngine
 		ID3D11HullShader* getHullShader() const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 
 	class D3D11GpuGeometryProgram : public D3D11GpuProgram
@@ -92,7 +104,10 @@ namespace CamelotEngine
 		ID3D11GeometryShader* getGeometryShader(void) const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 
 	class D3D11GpuComputeProgram : public D3D11GpuProgram
@@ -106,6 +121,9 @@ namespace CamelotEngine
 		ID3D11ComputeShader* getComputeShader(void) const;
 		void loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode);
 	protected:
-		void unloadImpl(void);
+		/**
+		 * @copydoc GpuProgram::destroy_internal().
+		 */
+		void destroy_internal();
 	};
 }

+ 2 - 2
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgram.h

@@ -43,9 +43,9 @@ namespace CamelotEngine
         void loadFromSource();
 
         /**
-         * @copydoc GpuProgram::unload_internal()
+         * @copydoc HighLevelGpuProgram::destroy_internal()
          */
-        void unload_internal();
+        void destroy_internal();
 
 	private:
 		bool mColumnMajorMatrices;

+ 2 - 7
CamelotD3D11RenderSystem/Include/CmD3D11Texture.h

@@ -74,14 +74,9 @@ namespace CamelotEngine
 		void initialize_internal();
 
 		/**
-		 * @copydoc Texture::createInternalResourcesImpl
+		 * @brief	Resource::destroy_internal
 		 */
-		void createInternalResourcesImpl();
-		
-		/**
-		 * @copydoc Texture::freeInternalResourcesImpl
-		 */
-		void freeInternalResourcesImpl();
+		void destroy_internal();
 
 		TextureView* createView();
 		void destroyView(TextureView* view);

+ 25 - 27
CamelotD3D11RenderSystem/Source/CmD3D11GpuProgram.cpp

@@ -19,7 +19,7 @@ namespace CamelotEngine
 
 	void D3D11GpuProgram::loadFromSource(void)
 	{
-		CM_EXCEPT(RenderingAPIException, "DirectX 11 doesn't support assembly shaders.");
+
 	}
 
 	D3D11GpuVertexProgram::D3D11GpuVertexProgram(const String& profile) 
@@ -28,11 +28,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuVertexProgram::~D3D11GpuVertexProgram()
-	{
-		// have to call this here reather than in Resource destructor
-		// since calling virtual methods in base destructors causes crash
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuVertexProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob*  microcode)
 	{
@@ -59,9 +55,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuVertexProgram::unloadImpl(void)
+	void D3D11GpuVertexProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mVertexShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11VertexShader * D3D11GpuVertexProgram::getVertexShader( void ) const
@@ -75,9 +73,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuFragmentProgram::~D3D11GpuFragmentProgram()
-	{
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuFragmentProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
 	{
@@ -103,9 +99,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuFragmentProgram::unloadImpl(void)
+	void D3D11GpuFragmentProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mPixelShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11PixelShader * D3D11GpuFragmentProgram::getPixelShader( void ) const
@@ -119,9 +117,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuGeometryProgram::~D3D11GpuGeometryProgram()
-	{
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuGeometryProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
 	{
@@ -147,9 +143,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuGeometryProgram::unloadImpl(void)
+	void D3D11GpuGeometryProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mGeometryShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11GeometryShader * D3D11GpuGeometryProgram::getGeometryShader(void) const
@@ -163,9 +161,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuDomainProgram::~D3D11GpuDomainProgram()
-	{
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuDomainProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
 	{
@@ -191,9 +187,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuDomainProgram::unloadImpl(void)
+	void D3D11GpuDomainProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mDomainShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11DomainShader * D3D11GpuDomainProgram::getDomainShader(void) const
@@ -207,9 +205,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuHullProgram::~D3D11GpuHullProgram()
-	{
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuHullProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
 	{
@@ -235,9 +231,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuHullProgram::unloadImpl(void)
+	void D3D11GpuHullProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mHullShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11HullShader* D3D11GpuHullProgram::getHullShader(void) const
@@ -251,9 +249,7 @@ namespace CamelotEngine
 	{ }
 
 	D3D11GpuComputeProgram::~D3D11GpuComputeProgram()
-	{
-		unload_internal(); 
-	}
+	{ }
 
 	void D3D11GpuComputeProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
 	{
@@ -279,9 +275,11 @@ namespace CamelotEngine
 		}
 	}
 
-	void D3D11GpuComputeProgram::unloadImpl(void)
+	void D3D11GpuComputeProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mComputeShader);
+
+		D3D11GpuProgram::destroy_internal();
 	}
 
 	ID3D11ComputeShader* D3D11GpuComputeProgram::getComputeShader(void) const

+ 4 - 2
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgram.cpp

@@ -24,7 +24,7 @@ namespace CamelotEngine
 
 	D3D11HLSLProgram::~D3D11HLSLProgram()
 	{
-		unload_internal();
+
 	}
 
     void D3D11HLSLProgram::loadFromSource()
@@ -80,10 +80,12 @@ namespace CamelotEngine
 		SAFE_RELEASE(microcode);
 	}
 
-    void D3D11HLSLProgram::unload_internal()
+    void D3D11HLSLProgram::destroy_internal()
 	{
 		mAssemblerProgram = nullptr;
 		mMicrocode.clear();
+
+		HighLevelGpuProgram::destroy_internal();
 	}
 
 	const String& D3D11HLSLProgram::getLanguage() const

+ 29 - 32
CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp

@@ -31,9 +31,7 @@ namespace CamelotEngine
 
 	D3D11Texture::~D3D11Texture()
 	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		freeInternalResources();			
+			
 	}
 
 	void D3D11Texture::copyImpl(TexturePtr& target)
@@ -96,33 +94,28 @@ namespace CamelotEngine
 	{
 		THROW_IF_NOT_RENDER_THREAD
 
-		createInternalResources();
-
-		Resource::initialize_internal();
-	}
-
-	void D3D11Texture::createInternalResourcesImpl()
-	{
-		// load based on tex.type
-		switch (getTextureType())
+			// load based on tex.type
+			switch (getTextureType())
 		{
-		case TEX_TYPE_1D:
-			_create1DTex();
-			break;
-		case TEX_TYPE_2D:
-		case TEX_TYPE_CUBE_MAP:
-			_create2DTex();
-			break;
-		case TEX_TYPE_3D:
-			_create3DTex();
-			break;
-		default:
-			freeInternalResources();
-			CM_EXCEPT(RenderingAPIException, "Unknown texture type");
+			case TEX_TYPE_1D:
+				_create1DTex();
+				break;
+			case TEX_TYPE_2D:
+			case TEX_TYPE_CUBE_MAP:
+				_create2DTex();
+				break;
+			case TEX_TYPE_3D:
+				_create3DTex();
+				break;
+			default:
+				destroy_internal();
+				CM_EXCEPT(RenderingAPIException, "Unknown texture type");
 		}
+
+		Resource::initialize_internal();
 	}
 
-	void D3D11Texture::freeInternalResourcesImpl()
+	void D3D11Texture::destroy_internal()
 	{
 		SAFE_RELEASE(mTex);
 		SAFE_RELEASE(mShaderResourceView);
@@ -130,6 +123,10 @@ namespace CamelotEngine
 		SAFE_RELEASE(m2DTex);
 		SAFE_RELEASE(m3DTex);
 		SAFE_RELEASE(mStagingBuffer);
+
+		clearBufferViews();
+
+		IDestroyable::destroy();
 	}
 
 	void D3D11Texture::_create1DTex()
@@ -180,7 +177,7 @@ namespace CamelotEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -189,7 +186,7 @@ namespace CamelotEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}
@@ -295,7 +292,7 @@ namespace CamelotEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -304,7 +301,7 @@ namespace CamelotEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}
@@ -420,7 +417,7 @@ namespace CamelotEngine
 		// Check result and except if failed
 		if (FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
 		}
@@ -429,7 +426,7 @@ namespace CamelotEngine
 
 		if(FAILED(hr) || device.hasError())
 		{
-			freeInternalResources();
+			destroy_internal();
 			String errorDescription = device.getErrorDescription();
 			CM_EXCEPT(RenderingAPIException, "Can't get base texture\nError Description:" + errorDescription);
 		}

+ 15 - 6
CamelotD3D9Renderer/Include/CmD3D9GpuProgram.h

@@ -44,8 +44,6 @@ namespace CamelotEngine {
 		virtual void initialize_internal(void);
 		/** Loads this program to specified device */
 		virtual void initialize_internal(IDirect3DDevice9* d3d9Device);
-		/** Overridden from GpuProgram */
-		virtual void unload(void);
 
         /** Sets whether matrix packing in column-major order. */ 
         void setColumnMajorMatrices(bool columnMajor) { mColumnMajorMatrices = columnMajor; }
@@ -67,6 +65,11 @@ namespace CamelotEngine {
 
 		D3D9GpuProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 
+		/**
+		 * @copydoc GpuProgram::destroy_internal.
+		 */
+		void destroy_internal();
+
         /** Overridden from GpuProgram */
         void loadFromSource(void);
 		/** Loads this program from source to specified device */
@@ -94,8 +97,6 @@ namespace CamelotEngine {
     public:
 		~D3D9GpuVertexProgram();
         
-		void unload(void);
-
 		/// Gets the vertex shader
         IDirect3DVertexShader9* getVertexShader(void);
 
@@ -110,6 +111,11 @@ namespace CamelotEngine {
 
 		D3D9GpuVertexProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 
+		/**
+		 * @copydoc D3D9GpuProgram::destroy_internal.
+		 */
+		void destroy_internal();
+
         void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode);
 
 	protected:
@@ -125,8 +131,6 @@ namespace CamelotEngine {
     public:
 		~D3D9GpuFragmentProgram();
 
-		void unload(void);
-
         /// Gets the pixel shader
         IDirect3DPixelShader9* getPixelShader(void);
 
@@ -141,6 +145,11 @@ namespace CamelotEngine {
 
 		D3D9GpuFragmentProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile);
 
+		/**
+		 * @copydoc D3D9GpuProgram::destroy_internal.
+		 */
+		void destroy_internal();
+
         void loadFromMicrocode(IDirect3DDevice9* d3d9Device, ID3DXBuffer* microcode);
 
 	protected:

+ 3 - 2
CamelotD3D9Renderer/Include/CmD3D9HLSLProgram.h

@@ -94,10 +94,11 @@ namespace CamelotEngine {
         /** Internal load implementation, must be implemented by subclasses.
         */
         void loadFromSource(void);
+
 		/**
-		 * @copydoc GpuProgram::unload_internal()
+		 * @copydoc HighLevelGpuProgram::destroy_internal.
 		 */
-        void unload_internal(void);
+        void destroy_internal();
 
         String mPreprocessorDefines;
         bool mColumnMajorMatrices;

+ 3 - 5
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -137,6 +137,8 @@ namespace CamelotEngine {
 		/// overriden from Resource
 		void initialize_internal();	
 
+		void destroy_internal();
+
 		/// overridden from Texture
 		void copyImpl(TexturePtr& target);
 
@@ -155,12 +157,8 @@ namespace CamelotEngine {
 
 		/// @copydoc Resource::calculateSize
 		UINT32 calculateSize(void) const;
-		/// @copydoc Texture::createInternalResourcesImpl
-		void createInternalResourcesImpl(void);
 		/// Creates this texture resources on the specified device.
-		void createInternalResourcesImpl(IDirect3DDevice9* d3d9Device);
-		/// free internal resources
-		void freeInternalResourcesImpl(void);
+		void createInternalResources(IDirect3DDevice9* d3d9Device);
 		/// internal method, set Texture class final texture protected attributes
 		void _setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources, 
 			unsigned long width, unsigned long height, unsigned long depth, PixelFormat format);

+ 11 - 7
CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp

@@ -104,10 +104,12 @@ namespace CamelotEngine {
 			loadFromSource(d3d9Device);
 		}
 	}
-	//-----------------------------------------------------------------------------
-	void D3D9GpuProgram::unload(void)
+	//----------------------------------------------------------------------------
+	void D3D9GpuProgram::destroy_internal()
 	{
 		SAFE_RELEASE(mpExternalMicrocode);
+
+		GpuProgram::destroy_internal();
 	}
 	//-----------------------------------------------------------------------------
     void D3D9GpuProgram::loadFromSource(void)
@@ -213,7 +215,7 @@ namespace CamelotEngine {
 		}
     }
 	//-----------------------------------------------------------------------------
-    void D3D9GpuVertexProgram::unload(void)
+    void D3D9GpuVertexProgram::destroy_internal(void)
     {
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -224,8 +226,9 @@ namespace CamelotEngine {
 			SAFE_RELEASE(it->second);
 			++it;
 		}
-		mMapDeviceToVertexShader.clear();		
-		D3D9GpuProgram::unload();
+		mMapDeviceToVertexShader.clear();	
+
+		D3D9GpuProgram::destroy_internal();
     }
 
 	//-----------------------------------------------------------------------------
@@ -317,7 +320,7 @@ namespace CamelotEngine {
 		}
     }
 	//-----------------------------------------------------------------------------
-    void D3D9GpuFragmentProgram::unload(void)
+    void D3D9GpuFragmentProgram::destroy_internal()
     {
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 
@@ -329,7 +332,8 @@ namespace CamelotEngine {
 			++it;
 		}
 		mMapDeviceToPixelShader.clear();	
-		D3D9GpuProgram::unload();
+
+		D3D9GpuProgram::destroy_internal();
     }
 	//-----------------------------------------------------------------------------
 	void D3D9GpuFragmentProgram::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)

+ 15 - 18
CamelotD3D9Renderer/Source/CmD3D9HLSLProgram.cpp

@@ -500,20 +500,17 @@ namespace CamelotEngine {
             CM_EXCEPT(RenderingAPIException, message);
         }
 
-		if (!mCompileError)
-		{
-			String hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
-
-			// Create a low-level program, give it the same name as us
-			mAssemblerProgram = 
-				GpuProgramManager::instance().createProgram(
-				"",// dummy source, since we'll be using microcode
-				"",
-				hlslProfile,
-				mType, 
-				GPP_NONE);
-			static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
-		}
+		hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);
+
+		// Create a low-level program, give it the same name as us
+		mAssemblerProgram = 
+			GpuProgramManager::instance().createProgram(
+			"",// dummy source, since we'll be using microcode
+			"",
+			hlslProfile,
+			mType, 
+			GPP_NONE);
+		static_cast<D3D9GpuProgram*>(mAssemblerProgram.get())->setExternalMicrocode(mpMicroCode);
 
 		D3D9HLSLParamParser paramParser(constTable);
 		mParametersDesc = paramParser.buildParameterDescriptions();
@@ -521,11 +518,11 @@ namespace CamelotEngine {
 		SAFE_RELEASE(constTable);
     }
     //-----------------------------------------------------------------------
-    void D3D9HLSLProgram::unload_internal(void)
+    void D3D9HLSLProgram::destroy_internal()
     {
         SAFE_RELEASE(mpMicroCode);
         
-		HighLevelGpuProgram::unload_internal();
+		HighLevelGpuProgram::destroy_internal();
     }
 	//-----------------------------------------------------------------------
 	LPD3DXBUFFER D3D9HLSLProgram::getMicroCode()
@@ -545,12 +542,12 @@ namespace CamelotEngine {
     //-----------------------------------------------------------------------
     D3D9HLSLProgram::~D3D9HLSLProgram()
     {
-        unload_internal();
+
     }
     //-----------------------------------------------------------------------
     bool D3D9HLSLProgram::isSupported(void) const
     {
-        if (mCompileError || !isRequiredCapabilitiesSupported())
+        if (!isRequiredCapabilitiesSupported())
             return false;
 
 		String hlslProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);

+ 40 - 53
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -59,25 +59,6 @@ namespace CamelotEngine
 	/****************************************************************************************/
 	D3D9Texture::~D3D9Texture()
 	{	
-		THROW_IF_NOT_RENDER_THREAD;
-
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-		
-        // have to call this here reather than in Resource destructor
-        // since calling virtual methods in base destructors causes crash
-		freeInternalResources();			
-
-		// Free memory allocated per device.
-		DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.begin();
-		while (it != mMapDeviceToTextureResources.end())
-		{
-			TextureResources* textureResource = it->second;
-			
-			SAFE_DELETE(textureResource);
-			++it;
-		}		
-		mMapDeviceToTextureResources.clear();
-		mSurfaceList.clear();		
 	}
 	/****************************************************************************************/
 	PixelData D3D9Texture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
@@ -220,28 +201,47 @@ namespace CamelotEngine
 	/****************************************************************************************/
 	void D3D9Texture::initialize_internal()
 	{ 
-		THROW_IF_NOT_RENDER_THREAD
+		THROW_IF_NOT_RENDER_THREAD;
 
-		createInternalResources();
+		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
+		{
+			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
+
+			createInternalResources(d3d9Device);
+		}
 
 		Resource::initialize_internal();
 	}
 	/****************************************************************************************/
-	void D3D9Texture::freeInternalResourcesImpl()
-	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
+	void D3D9Texture::destroy_internal()
+	{ 
+		THROW_IF_NOT_RENDER_THREAD;
 
 		DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.begin();
-
 		while (it != mMapDeviceToTextureResources.end())
 		{
 			TextureResources* textureResource = it->second;
 
 			freeTextureResources(it->first, textureResource);			
 			++it;
-		}						
-	}
+		}
+
+		it = mMapDeviceToTextureResources.begin();
+		while (it != mMapDeviceToTextureResources.end())
+		{
+			TextureResources* textureResource = it->second;
+
+			SAFE_DELETE(textureResource);
+			++it;
+		}		
+
+		mMapDeviceToTextureResources.clear();
+		mSurfaceList.clear();	
+		
+		clearBufferViews();
 
+		IDestroyable::destroy();
+	}
 	/****************************************************************************************/
 	D3D9Texture::TextureResources* D3D9Texture::getTextureResources(IDirect3DDevice9* d3d9Device)
 	{		
@@ -326,20 +326,7 @@ namespace CamelotEngine
 
 	}
 	/****************************************************************************************/
-    void D3D9Texture::createInternalResourcesImpl(void)
-	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-		for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
-		{
-			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
-
-			createInternalResourcesImpl(d3d9Device);
-		}
-	}
-
-	/****************************************************************************************/
-	void D3D9Texture::createInternalResourcesImpl(IDirect3DDevice9* d3d9Device)
+	void D3D9Texture::createInternalResources(IDirect3DDevice9* d3d9Device)
 	{		
 		TextureResources* textureResources;			
 
@@ -362,7 +349,7 @@ namespace CamelotEngine
 			_createVolumeTex(d3d9Device);
 			break;
 		default:
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(InternalErrorException, "Unknown texture type");
 		}
 	}
@@ -464,7 +451,7 @@ namespace CamelotEngine
 			hr = textureResources->pFSAASurface->GetDesc(&desc);
 			if (FAILED(hr))
 			{
-				freeInternalResources();
+				destroy_internal();
 				CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -487,7 +474,7 @@ namespace CamelotEngine
 			hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
 			if (FAILED(hr))
 			{
-				freeInternalResources();
+				destroy_internal();
 				CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -509,7 +496,7 @@ namespace CamelotEngine
 			// check result and except if failed
 			if (FAILED(hr))
 			{
-				freeInternalResources();
+				destroy_internal();
 				CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -517,7 +504,7 @@ namespace CamelotEngine
 			hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
 			if (FAILED(hr))
 			{
-				freeInternalResources();
+				destroy_internal();
 				CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -527,7 +514,7 @@ namespace CamelotEngine
 			hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
 			if (FAILED(hr))
 			{
-				freeInternalResources();
+				destroy_internal();
 				CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 			}
 
@@ -616,7 +603,7 @@ namespace CamelotEngine
 		// check result and except if failed
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 		}
 
@@ -624,7 +611,7 @@ namespace CamelotEngine
 		hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 		}
 		
@@ -634,7 +621,7 @@ namespace CamelotEngine
 		hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 		}
 
@@ -721,7 +708,7 @@ namespace CamelotEngine
 		// check result and except if failed
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
 		}
 
@@ -729,7 +716,7 @@ namespace CamelotEngine
 		hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
 		}
 		
@@ -739,7 +726,7 @@ namespace CamelotEngine
 		hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
 		if (FAILED(hr))
 		{
-			freeInternalResources();
+			destroy_internal();
 			CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
 		}
 		_setFinalAttributes(d3d9Device, textureResources,

+ 1 - 7
CamelotGLRenderer/Include/CmGLTexture.h

@@ -47,8 +47,6 @@ namespace CamelotEngine {
 
         GLuint getGLID() const;
 		
-		void getCustomAttribute(const String& name, void* pData);
-
 		/** Return hardware pixel buffer for a surface. This buffer can then
 			be used to copy data from and to a particular level of the texture.
 			@param face 	Face number, in case of a cubemap texture. Must be 0
@@ -70,17 +68,13 @@ namespace CamelotEngine {
 		GLTexture(GLSupport& support);
 
 		void initialize_internal();
+		void destroy_internal();
 
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face);
 		void unlockImpl();
 
 		void copyImpl(TexturePtr& target);
 
-		/// @copydoc Texture::createInternalResourcesImpl
-		void createInternalResourcesImpl(void);
-        /// @copydoc Resource::freeInternalResourcesImpl
-        void freeInternalResourcesImpl(void);
-
 		/** internal method, create GLHardwarePixelBuffers for every face and
 			 mipmap level. This method must be called after the GL texture object was created,
 			the number of mipmaps was set (GL_TEXTURE_MAX_LEVEL) and glTexImageXD was called to

+ 91 - 104
CamelotGLRenderer/Source/CmGLTexture.cpp

@@ -65,101 +65,23 @@ namespace CamelotEngine {
 
     GLTexture::~GLTexture()
     {
-		THROW_IF_NOT_RENDER_THREAD;
-
-		freeInternalResources();
     }
 
 	void GLTexture::initialize_internal()
 	{
-		createInternalResources();
-
-		Resource::initialize_internal();
-	}
-
-    GLenum GLTexture::getGLTextureTarget(void) const
-    {
-        switch(mTextureType)
-        {
-            case TEX_TYPE_1D:
-                return GL_TEXTURE_1D;
-            case TEX_TYPE_2D:
-				if(mFSAA > 0)
-					return GL_TEXTURE_2D_MULTISAMPLE;
-				else
-					return GL_TEXTURE_2D;
-            case TEX_TYPE_3D:
-                return GL_TEXTURE_3D;
-            case TEX_TYPE_CUBE_MAP:
-                return GL_TEXTURE_CUBE_MAP;
-            default:
-                return 0;
-        };
-    }
-
-	GLuint GLTexture::getGLID() const
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		return mTextureID;
-	}
-
-	//* Creation / loading methods ********************************************
-	PixelData GLTexture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
-	{
-		if(mLockedBuffer != nullptr)
-			CM_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
-
-		UINT32 mipWidth = mipLevel >> mWidth;
-		UINT32 mipHeight = mipLevel >> mHeight;
-		UINT32 mipDepth = mipLevel >> mDepth;
-
-		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
-
-		mLockedBuffer = getBuffer(face, mipLevel);
-		lockedArea.data = mLockedBuffer->lock(options);
-
-		return lockedArea;
-	}
-	/****************************************************************************************/
-	void GLTexture::unlockImpl()
-	{
-		if(mLockedBuffer == nullptr)
-			CM_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
-
-		mLockedBuffer->unlock();
-		mLockedBuffer = nullptr;
-	}
-	/****************************************************************************************/ 
-	void GLTexture::copyImpl(TexturePtr& target)
-	{
-		size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
-
-		GLTexture* glTexture = static_cast<GLTexture*>(target.get());
-		for(unsigned int face=0; face<getNumFaces(); face++)
-		{
-			for(unsigned int mip=0; mip<=numMips; mip++)
-			{
-				glTexture->getBuffer(face, mip)->blit(getBuffer(face, mip));
-			}
-		}
-	}
-	/****************************************************************************************/
-	void GLTexture::createInternalResourcesImpl(void)
-    {
 		// Convert to nearest power-of-two size if required
-        mWidth = GLPixelUtil::optionalPO2(mWidth);      
-        mHeight = GLPixelUtil::optionalPO2(mHeight);
-        mDepth = GLPixelUtil::optionalPO2(mDepth);
+		mWidth = GLPixelUtil::optionalPO2(mWidth);      
+		mHeight = GLPixelUtil::optionalPO2(mHeight);
+		mDepth = GLPixelUtil::optionalPO2(mDepth);
 
 		// Adjust format if required
 		mFormat = TextureManager::instance().getNativeFormat(mTextureType, mFormat, mUsage);
-		
+
 		// Check requested number of mipmaps
 		UINT32 maxMips = GLPixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
 		if(mNumMipmaps>maxMips)
 			mNumMipmaps = maxMips;
-		
+
 		if((mUsage & TU_RENDERTARGET) != 0)
 		{
 			mNumMipmaps = 1;
@@ -180,23 +102,23 @@ namespace CamelotEngine {
 		}
 
 		// Generate texture name
-        glGenTextures( 1, &mTextureID );
-		
+		glGenTextures( 1, &mTextureID );
+
 		// Set texture type
 		glBindTexture( getGLTextureTarget(), mTextureID );
-        
+
 		// This needs to be set otherwise the texture doesn't get rendered
 		glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
-        
-        // Set some misc default parameters so NVidia won't complain, these can of course be changed later
-        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+		// Set some misc default parameters so NVidia won't complain, these can of course be changed later
+		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		if (GLEW_VERSION_1_2)
 		{
 			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		}
-		
+
 		// Allocate internal buffer so that glTexSubImageXD can be used
 		// Internal format
 		GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
@@ -274,13 +196,87 @@ namespace CamelotEngine {
 		createSurfaceList();
 		// Get final internal format
 		mFormat = getBuffer(0,0)->getFormat();
+
+		Resource::initialize_internal();
 	}
-	//--------------------------------------------------------------------------------------------
-    void GLTexture::freeInternalResourcesImpl()
-    {
+
+	void GLTexture::destroy_internal()
+	{
 		mSurfaceList.clear();
-        glDeleteTextures( 1, &mTextureID );
+		glDeleteTextures( 1, &mTextureID );
+
+		clearBufferViews();
+
+		IDestroyable::destroy();
+	}
+
+    GLenum GLTexture::getGLTextureTarget(void) const
+    {
+        switch(mTextureType)
+        {
+            case TEX_TYPE_1D:
+                return GL_TEXTURE_1D;
+            case TEX_TYPE_2D:
+				if(mFSAA > 0)
+					return GL_TEXTURE_2D_MULTISAMPLE;
+				else
+					return GL_TEXTURE_2D;
+            case TEX_TYPE_3D:
+                return GL_TEXTURE_3D;
+            case TEX_TYPE_CUBE_MAP:
+                return GL_TEXTURE_CUBE_MAP;
+            default:
+                return 0;
+        };
     }
+
+	GLuint GLTexture::getGLID() const
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		return mTextureID;
+	}
+
+	//* Creation / loading methods ********************************************
+	PixelData GLTexture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
+	{
+		if(mLockedBuffer != nullptr)
+			CM_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
+
+		UINT32 mipWidth = mipLevel >> mWidth;
+		UINT32 mipHeight = mipLevel >> mHeight;
+		UINT32 mipDepth = mipLevel >> mDepth;
+
+		PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
+
+		mLockedBuffer = getBuffer(face, mipLevel);
+		lockedArea.data = mLockedBuffer->lock(options);
+
+		return lockedArea;
+	}
+	/****************************************************************************************/
+	void GLTexture::unlockImpl()
+	{
+		if(mLockedBuffer == nullptr)
+			CM_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
+
+		mLockedBuffer->unlock();
+		mLockedBuffer = nullptr;
+	}
+	/****************************************************************************************/ 
+	void GLTexture::copyImpl(TexturePtr& target)
+	{
+		size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
+
+		GLTexture* glTexture = static_cast<GLTexture*>(target.get());
+		for(unsigned int face=0; face<getNumFaces(); face++)
+		{
+			for(unsigned int mip=0; mip<=numMips; mip++)
+			{
+				glTexture->getBuffer(face, mip)->blit(getBuffer(face, mip));
+			}
+		}
+	}
 	//---------------------------------------------------------------------------------------------
 	void GLTexture::createSurfaceList()
 	{
@@ -320,15 +316,6 @@ namespace CamelotEngine {
 		assert(idx < mSurfaceList.size());
 		return mSurfaceList[idx];
 	}
-	//---------------------------------------------------------------------------------------------
-	void GLTexture::getCustomAttribute(const String& name, void* pData)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		if (name == "GLID")
-			*static_cast<GLuint*>(pData) = mTextureID;
-	}
-	
 }
 
 #undef THROW_IF_NOT_RENDER_THREAD

+ 10 - 2
CamelotGLRenderer/Source/GLSL/include/CmGLSLGpuProgram.h

@@ -79,8 +79,16 @@ namespace CamelotEngine {
 
         /// Overridden from GpuProgram
         void loadFromSource(void);
-		/// @copydoc Resource::loadImpl
-		void initialize_internal(void);
+
+		/**
+		 * @copydoc GpuProgram::initialize_internal
+		 */
+		void initialize_internal();
+
+		/**
+		 * @copydoc GpuProgram::destroy_internal
+		 */
+		void destroy_internal();
     };
 }
 

+ 2 - 2
CamelotGLRenderer/Source/GLSL/include/CmGLSLProgram.h

@@ -109,9 +109,9 @@ namespace CamelotEngine {
         void loadFromSource(void);
 
 		/**
-		 * @copydoc GpuProgram::unload_internal()
+		 * @copydoc GpuProgram::destroy_internal()
 		 */
-		void unload_internal();
+		void destroy_internal();
 
 	private:
 		/// GL handle for shader object

+ 6 - 3
CamelotGLRenderer/Source/GLSL/src/CmGLSLGpuProgram.cpp

@@ -70,9 +70,6 @@ namespace CamelotEngine {
     //-----------------------------------------------------------------------
     GLSLGpuProgram::~GLSLGpuProgram()
     {
-        // have to call this here reather than in Resource destructor
-        // since calling virtual methods in base destructors causes crash
-        unload_internal(); 
     }
 	//-----------------------------------------------------------------------------
     void GLSLGpuProgram::initialize_internal(void)
@@ -85,5 +82,11 @@ namespace CamelotEngine {
     {
 		// nothing to load
 	}
+	//-----------------------------------------------------------------------------
+	void GLSLGpuProgram::destroy_internal()
+	{
+		// Nothing to destroy
+		GpuProgram::destroy();
+	}
 }
 

+ 7 - 7
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgram.cpp

@@ -44,11 +44,6 @@ THE SOFTWARE.
 
 namespace CamelotEngine 
 {
-    //---------------------------------------------------------------------------
-    GLSLProgram::~GLSLProgram()
-    {
-        unload_internal();
-    }
 	//-----------------------------------------------------------------------
 	GLSLProgram::GLSLProgram(const String& source, const String& entryPoint, const String& language, 
 		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired)
@@ -59,6 +54,11 @@ namespace CamelotEngine
 		// Manually assign language now since we use it immediately
 		mSyntaxCode = "glsl";
 
+	}
+	//---------------------------------------------------------------------------
+	GLSLProgram::~GLSLProgram()
+	{
+
 	}
     //-----------------------------------------------------------------------
 	void GLSLProgram::loadFromSource(void)
@@ -172,7 +172,7 @@ namespace CamelotEngine
 		paramParser.buildVertexDeclaration(mGLHandle, mVertexDeclaration);
 	}
 	//---------------------------------------------------------------------------
-	void GLSLProgram::unload_internal()
+	void GLSLProgram::destroy_internal()
 	{   
 		// We didn't create mAssemblerProgram through a manager, so override this
 		// implementation so that we don't try to remove it from one. Since getCreator()
@@ -182,7 +182,7 @@ namespace CamelotEngine
 		if (isSupported())
 			glDeleteShader(mGLHandle);
 
-		HighLevelGpuProgram::unload_internal();
+		HighLevelGpuProgram::destroy_internal();
 	}
     //-----------------------------------------------------------------------
     const String& GLSLProgram::getLanguage(void) const

+ 39 - 49
CamelotRenderer/Include/CmGpuProgram.h

@@ -97,57 +97,14 @@ namespace CamelotEngine {
 	*/
 	class CM_EXPORT GpuProgram : public Resource
 	{
-	protected:
-		/// The type of the program
-		GpuProgramType mType;
-		/// Does this (geometry) program require adjacency information?
-		bool mNeedsAdjacencyInfo;
-		/// Name of the shader entry method
-		String mEntryPoint;
-		/// Shader profiler that we are targeting (e.g. vs_1_1, etc.). Make sure profile matches the type.
-		GpuProgramProfile mProfile;
-        /// The assembler source of the program (may be blank until file loaded)
-        String mSource;
-        /// Syntax code e.g. arbvp1, vs_2_0 etc
-        String mSyntaxCode;
-		/// Did we encounter a compilation error?
-		bool mCompileError;
-
-		/**
-		 * @brief	Contains information about all parameters in a shader.
-		 */
-		GpuParamDesc mParametersDesc;
-
-        /** Internal method returns whether required capabilities for this program is supported.
-        */
-        bool isRequiredCapabilitiesSupported(void) const;
-
-		/// @copydoc Resource::calculateSize
-		size_t calculateSize(void) const { return 0; } // TODO 
-
-		void throwIfNotRenderThread() const;
-
 	public:
 		virtual ~GpuProgram();
 
-		/**
-		 * @brief	Initializes the gpu program. This must be called right after the program is constructed. 
-		 * 			Called by GpuProgramManager upon creation, so usually you don't want to call this manually. 
-		 * 			
-		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
-		 */
-		void initialize();
-
 		/**
 		 * @brief	Performs GpuProgram initialization. Only callable from the render thread.
 		 */
 		virtual void initialize_internal();
 
-		/**
-		 * @brief	Unloads the GpuProgram. Only callable from the render thread.
-		 */
-		virtual void unload_internal();
-
         /** Gets the syntax code for this program e.g. arbvp1, fp20, vs_1_1 etc */
         virtual const String& getSyntaxCode(void) const { return mSyntaxCode; }
 
@@ -190,13 +147,46 @@ namespace CamelotEngine {
         */
         virtual const String& getLanguage(void) const;
 
-		/** Did this program encounter a compile error when loading?
-		*/
-		virtual bool hasCompileError(void) const { return mCompileError; }
+	protected:
+		/// The type of the program
+		GpuProgramType mType;
+		/// Does this (geometry) program require adjacency information?
+		bool mNeedsAdjacencyInfo;
+		/// Name of the shader entry method
+		String mEntryPoint;
+		/// Shader profiler that we are targeting (e.g. vs_1_1, etc.). Make sure profile matches the type.
+		GpuProgramProfile mProfile;
+        /// The assembler source of the program (may be blank until file loaded)
+        String mSource;
+        /// Syntax code e.g. arbvp1, vs_2_0 etc
+        String mSyntaxCode;
 
-		/** Reset a compile error if it occurred, allowing the load to be retried
-		*/
-		virtual void resetCompileError(void) { mCompileError = false; }
+		/**
+		 * @brief	Contains information about all parameters in a shader.
+		 */
+		GpuParamDesc mParametersDesc;
+
+		/**
+		 * @brief	Initializes the gpu program. This must be called right after the program is constructed. 
+		 * 			Called by GpuProgramManager upon creation, so usually you don't want to call this manually. 
+		 * 			
+		 * @note	Initialization is not done immediately, and is instead just scheduled on the render thread.
+		 */
+		void initialize();
+
+		/**
+		 * @copydoc Resource::destroy_internal.
+		 */
+		virtual void destroy_internal();
+
+        /** Internal method returns whether required capabilities for this program is supported.
+        */
+        bool isRequiredCapabilitiesSupported(void) const;
+
+		/// @copydoc Resource::calculateSize
+		size_t calculateSize(void) const { return 0; } // TODO 
+
+		void throwIfNotRenderThread() const;
 
     protected:
 		friend class GpuProgramManager;

+ 5 - 5
CamelotRenderer/Include/CmHighLevelGpuProgram.h

@@ -84,11 +84,6 @@ namespace CamelotEngine {
 		 */
 		virtual void initialize_internal();
 
-		/**
-		 * @copydoc GpuProgram::unload_internal()
-		 */
-		virtual void unload_internal();
-
         /** @copydoc GpuProgram::getBindingDelegate */
         virtual GpuProgram* getBindingDelegate(void) { return mAssemblerProgram.get(); }
 
@@ -97,6 +92,11 @@ namespace CamelotEngine {
 		HighLevelGpuProgram(const String& source, const String& entryPoint, const String& language, 
 			GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired = false);
 
+		/**
+		 * @copydoc GpuProgram::unload_internal()
+		 */
+		virtual void destroy_internal();
+
         /// The underlying assembler program
         GpuProgramPtr mAssemblerProgram;
 

+ 18 - 5
CamelotRenderer/Include/CmResource.h

@@ -2,18 +2,21 @@
 
 #include "CmPrerequisites.h"
 #include "CmIReflectable.h"
+#include "CmIDestroyable.h"
 
 namespace CamelotEngine
 {
 	/**
 	 * @brief	Base class for all resources used in the engine.
 	 */
-	class CM_EXPORT Resource : public IReflectable
+	class CM_EXPORT Resource : public IReflectable, public IDestroyable
 	{
 	public:
 		Resource();
 		virtual ~Resource() {};
 
+
+
 		const String& getUUID() const { return mUUID; }
 
 		/**
@@ -27,12 +30,17 @@ namespace CamelotEngine
 		 */
 		void waitUntilInitialized();
 
+		/**
+		 * @copydoc	IDestroyable::destroy()
+		 * 			
+		 * 	@note	Destruction is not done immediately, and is instead just scheduled on the
+		 * 			render thread. Unless internalCall is specified, in which case it is destroyed
+		 * 			right away. But you should only do this when calling from the render thread.
+		 */
+		void destroy(bool internalCall = false);
+
 	protected:
 		friend class Resources;
-		//virtual void unload() = 0;
-
-		//virtual void calculateSize() = 0;
-		//virtual void reload();
 		
 		/**
 		 * @brief	Finishes up resource initialization. Usually called right after the resource is created.
@@ -41,6 +49,11 @@ namespace CamelotEngine
 		 */
 		virtual void initialize_internal();
 
+		/**
+		 * @brief	Destroys all texture resources, but doesn't actually delete the object.
+		 */
+		virtual void destroy_internal() {} // TODO - This is temporarily non-abstract
+
 		/**
 		 * @brief	Marks the resource as initialized.
 		 */

+ 1 - 41
CamelotRenderer/Include/CmTexture.h

@@ -137,13 +137,6 @@ namespace CamelotEngine {
         */
         virtual UINT32 getNumFaces() const;
 
-		/** Retrieve a platform or API-specific piece of information from this texture.
-		 This method of retrieving information should only be used if you know what you're doing.
-		 @param name The name of the attribute to retrieve
-		 @param pData Pointer to memory matching the type of data you want to retrieve.
-		*/
-		virtual void getCustomAttribute(const String& name, void* pData);
-
 		/**
 		 * @brief	Sets raw texture pixels for the specified mip level and texture face. Pixel format
 		 * 			must match the format of the texture.
@@ -258,15 +251,10 @@ namespace CamelotEngine {
 		 * 							
 		 * @note	Initialization is not done immediately, and is instead just scheduled on the
 		 * 			render thread. Unless internalCall is specified, in which case it is initialized
-		 * 			right away.
+		 * 			right away. But you should only do this when calling from the render thread.
 		 */
 		void initialize(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps, 
 			PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint, bool internalCall = false);
-		
-		/**
-		 * @brief	Performs GpuProgram initialization. Only callable from the render thread.
-		 */
-		virtual void initialize_internal() = 0;
 
 		virtual PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0) = 0;
 		virtual void unlockImpl() = 0;
@@ -276,34 +264,6 @@ namespace CamelotEngine {
 		/// @copydoc Resource::calculateSize
 		UINT32 calculateSize(void) const;
 
-        /** Creates the internal texture resources for this texture. 
-        @remarks
-            This method creates the internal texture resources (pixel buffers, 
-            texture surfaces etc) required to begin using this texture. You do
-            not need to call this method directly unless you are manually creating
-            a texture, in which case something must call it, after having set the
-            size and format of the texture (e.g. the ManualResourceLoader might
-            be the best one to call it). If you are not defining a manual texture,
-            or if you use one of the self-contained load...() methods, then it will be
-            called for you.
-        */
-        virtual void createInternalResources(void);
-
-        /** Frees internal texture resources for this texture. 
-        */
-        virtual void freeInternalResources(void);
-
-		/** Implementation of creating internal texture resources 
-		*/
-		virtual void createInternalResourcesImpl(void) = 0;
-
-		/** Implementation of freeing internal texture resources 
-		*/
-		virtual void freeInternalResourcesImpl(void) = 0;
-
-		/** Default implementation of unload which calls freeInternalResources */
-		void unloadImpl(void);
-
 		void throwIfNotRenderThread() const;
 
 		/************************************************************************/

+ 3 - 3
CamelotRenderer/Source/CmCgProgram.cpp

@@ -95,7 +95,7 @@ namespace CamelotEngine {
             "Unable to compile Cg program", mCgContext);
 
 		// ignore any previous error
-		if (mSelectedCgProfile != CG_PROFILE_UNKNOWN && !mCompileError)
+		if (mSelectedCgProfile != CG_PROFILE_UNKNOWN)
 		{
 			String sourceFromCg = cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM);
 
@@ -115,7 +115,7 @@ namespace CamelotEngine {
 
     void CgProgram::unload_internal(void)
     {
-		HighLevelGpuProgram::unload_internal();
+		HighLevelGpuProgram::destroy_internal();
     }
 
 	GpuParamsPtr CgProgram::createParameters()
@@ -154,7 +154,7 @@ namespace CamelotEngine {
 
     bool CgProgram::isSupported(void) const
     {
-        if (mCompileError || !isRequiredCapabilitiesSupported())
+        if (!isRequiredCapabilitiesSupported())
             return false;
 
 		String selectedProfile = GpuProgramManager::instance().gpuProgProfileToRSSpecificProfile(mProfile);

+ 8 - 21
CamelotRenderer/Source/CmGpuProgram.cpp

@@ -48,14 +48,13 @@ namespace CamelotEngine
     GpuProgram::GpuProgram(const String& source, const String& entryPoint, const String& language, 
 		GpuProgramType gptype, GpuProgramProfile profile, bool isAdjacencyInfoRequired) 
         :mSource(source), mEntryPoint(entryPoint), mSyntaxCode(language), mType(gptype),
-		mProfile(profile), mNeedsAdjacencyInfo(isAdjacencyInfoRequired), mCompileError(false)
+		mProfile(profile), mNeedsAdjacencyInfo(isAdjacencyInfoRequired)
     {
 
     }
 	//----------------------------------------------------------------------------
 	GpuProgram::~GpuProgram()
 	{
-		THROW_IF_NOT_RENDER_THREAD;
 	}
 	//-----------------------------------------------------------------------------
 	void GpuProgram::initialize()
@@ -65,32 +64,20 @@ namespace CamelotEngine
     //-----------------------------------------------------------------------------
     void GpuProgram::initialize_internal(void)
     {
-        // Call polymorphic load
-		try 
-		{
-			loadFromSource();
+		loadFromSource();
 
-			Resource::initialize_internal();
-		}
-		catch (const Exception&)
-		{
-			// will already have been logged
-			//LogManager::getSingleton().stream()
-			//	<< "Gpu program " << mName << " encountered an error "
-			//	<< "during loading and is thus not supported.";
-
-			mCompileError = true;
-		}
+		Resource::initialize_internal();
     }
-	//-----------------------------------------------------------------------------
-	void GpuProgram::unload_internal()
+	//---------------------------------------------------------------------------
+	void GpuProgram::destroy_internal()
 	{
-		THROW_IF_NOT_RENDER_THREAD;
+		// Nothing to destroy
+		IDestroyable::destroy();
 	}
     //-----------------------------------------------------------------------------
     bool GpuProgram::isSupported(void) const
     {
-        if (mCompileError || !isRequiredCapabilitiesSupported())
+        if (!isRequiredCapabilitiesSupported())
             return false;
 
 		RenderSystem* rs = CamelotEngine::RenderSystem::instancePtr();

+ 7 - 9
CamelotRenderer/Source/CmHighLevelGpuProgram.cpp

@@ -47,6 +47,11 @@ namespace CamelotEngine
         mAssemblerProgram(0)
     {
     }
+	//---------------------------------------------------------------------------
+	HighLevelGpuProgram::~HighLevelGpuProgram()
+	{
+
+	}
 	//---------------------------------------------------------------------------
 	void HighLevelGpuProgram::initialize(bool internalCall)
 	{
@@ -73,21 +78,14 @@ namespace CamelotEngine
 		Resource::initialize_internal();
     }
     //---------------------------------------------------------------------------
-    void HighLevelGpuProgram::unload_internal()
+    void HighLevelGpuProgram::destroy_internal()
     {   
         if (mAssemblerProgram != nullptr && mAssemblerProgram.get() != this)
         {
             mAssemblerProgram = nullptr;
         }
 
-		resetCompileError();
-
-		GpuProgram::unload_internal();
-    }
-    //---------------------------------------------------------------------------
-    HighLevelGpuProgram::~HighLevelGpuProgram()
-    {
-        // superclasses will trigger unload
+		GpuProgram::destroy_internal();
     }
 	//---------------------------------------------------------------------
 	HighLevelGpuProgramPtr HighLevelGpuProgram::create(const String& source, const String& entryPoint, 

+ 8 - 0
CamelotRenderer/Source/CmResource.cpp

@@ -26,6 +26,14 @@ namespace CamelotEngine
 		CM_THREAD_NOTIFY_ALL(mResourceLoadedCondition);
 	}
 
+	void Resource::destroy(bool internalCall)
+	{
+		if(internalCall)
+			destroy_internal();
+		else
+			RenderSystem::instancePtr()->queueCommand(boost::bind(&Texture::destroy_internal, this));
+	}
+
 	void Resource::waitUntilInitialized()
 	{
 #if CM_DEBUG_MODE

+ 0 - 23
CamelotRenderer/Source/CmTexture.cpp

@@ -93,22 +93,6 @@ namespace CamelotEngine {
 	{
 		return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
 	}
-	//-------------------------------------------------------------------------
-	void Texture::getCustomAttribute(const String& name, void* pData)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-	}
-	//-----------------------------------------------------------------------------
-	void Texture::createInternalResources(void)
-	{
-		createInternalResourcesImpl();
-	}
-	//-----------------------------------------------------------------------------
-	void Texture::freeInternalResources(void)
-	{
-		freeInternalResourcesImpl();
-		clearBufferViews();
-	}
 
 	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
 	{
@@ -224,13 +208,6 @@ namespace CamelotEngine {
 
 		copyImpl(target);
 	}
-	//-----------------------------------------------------------------------------
-	void Texture::unloadImpl(void)
-	{
-		THROW_IF_NOT_RENDER_THREAD;
-
-		freeInternalResources();
-	}
 	//----------------------------------------------------------------------------- 
 	void Texture::throwIfNotRenderThread() const
 	{

+ 11 - 0
CamelotRenderer/TODO.txt

@@ -20,6 +20,17 @@ Pass
  - Fix MaterialRTTI saving (Save params per gpuprogram is simplest and cleanest) (Maybe wait until I have the Parser sorted out?)
  - Fix how and when is GpuParamBlock created/destroyed. Needs to happen on the render thread
 
+Resource destruction:
+Resources keep a permanent reference to each resource so they are never freed
+ - Keep just a weak ptr?
+
+OR
+
+Keep a strong ptr, when Resource::destroy() internally calls Resources to remove the reference?
+And Resources.DestroyUnusedAssets destroys all with just 1 reference?
+
+Resource::destroy_internal is not abstract temporarily so I can test
+
 Shader parser (possible leave for later? But it might require Resource changes)
  - Static/Dynamic usage for GpuParamBlocks
  - Ability to mark param blocks as "Shared". Those would not get created with every pass instance and would require user to actually create and assign them

+ 2 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -157,6 +157,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\CamelotRenderer\Source\CmManagedDataBlock.cpp" />
+    <ClCompile Include="Source\CmIDestroyable.cpp" />
     <ClCompile Include="Source\CmInt2.cpp" />
     <ClCompile Include="Source\CmPixelData.cpp" />
     <ClCompile Include="Source\CmUUID.cpp" />
@@ -172,6 +173,7 @@
     <ClInclude Include="Include\CmException.h" />
     <ClInclude Include="Include\CmFileSerializer.h" />
     <ClInclude Include="Include\CmFileSystem.h" />
+    <ClInclude Include="Include\CmIDestroyable.h" />
     <ClInclude Include="Include\CmInt2.h" />
     <ClInclude Include="Include\CmIReflectable.h" />
     <ClInclude Include="Include\CmKeyValuePair.h" />

+ 6 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -207,6 +207,9 @@
     <ClInclude Include="Include\CmUtil.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmIDestroyable.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">
@@ -302,5 +305,8 @@
     <ClCompile Include="Source\CmPixelData.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmIDestroyable.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 25 - 0
CamelotUtility/Include/CmIDestroyable.h

@@ -0,0 +1,25 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+
+namespace CamelotEngine
+{
+	/**
+	 * @brief	Classes deriving from this interface need to be destroyed with the help of a destroy() method,
+	 * 			before their actual destructor is called.
+	 */
+	class CM_UTILITY_EXPORT IDestroyable
+	{
+	public:
+		IDestroyable();
+		virtual ~IDestroyable();
+
+		/**
+		 * @brief	Destroys this object. Make sure to call this before deleting the object.
+		 */
+		virtual void destroy();
+
+	private:
+		bool mDestroyed;
+	};
+}

+ 22 - 0
CamelotUtility/Source/CmIDestroyable.cpp

@@ -0,0 +1,22 @@
+#include "CmIDestroyable.h"
+#include "CmDebug.h"
+
+namespace CamelotEngine
+{
+	IDestroyable::IDestroyable()
+		:mDestroyed(false)
+	{ }
+
+	IDestroyable::~IDestroyable() 
+	{
+		if(!mDestroyed)
+		{
+			LOGWRN("Destructor called but object is not destroyed. Object will leak.")
+		}
+	}
+
+	void IDestroyable::destroy()
+	{
+		mDestroyed = true;
+	}
+}