Browse Source

Fixed multiple exceptions and deadlocks that were happening when attempting to exit the application

Marko Pintera 13 years ago
parent
commit
fda3ca2150
32 changed files with 229 additions and 203 deletions
  1. 55 49
      CamelotClient/CamelotClient.cpp
  2. 4 4
      CamelotClient/CamelotClient.vcxproj
  3. 0 1
      CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgramFactory.h
  4. 0 5
      CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgramFactory.cpp
  5. 2 1
      CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp
  6. 0 2
      CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h
  7. 6 10
      CamelotD3D9Renderer/Include/CmD3D9ResourceManager.h
  8. 0 2
      CamelotD3D9Renderer/Source/CmD3D9Device.cpp
  9. 3 0
      CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp
  10. 0 6
      CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp
  11. 2 0
      CamelotD3D9Renderer/Source/CmD3D9IndexBuffer.cpp
  12. 23 26
      CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp
  13. 1 1
      CamelotD3D9Renderer/Source/CmD3D9Resource.cpp
  14. 20 20
      CamelotD3D9Renderer/Source/CmD3D9ResourceManager.cpp
  15. 2 0
      CamelotD3D9Renderer/Source/CmD3D9Texture.cpp
  16. 2 0
      CamelotD3D9Renderer/Source/CmD3D9VertexBuffer.cpp
  17. 3 0
      CamelotD3D9Renderer/Source/CmD3D9VertexDeclaration.cpp
  18. 17 16
      CamelotGLRenderer/Source/CmGLRenderSystem.cpp
  19. 0 1
      CamelotGLRenderer/Source/GLSL/include/CmGLSLProgramFactory.h
  20. 0 7
      CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp
  21. 23 0
      CamelotRenderer/Include/CmApplication.h
  22. 0 1
      CamelotRenderer/Include/CmCommandQueue.h
  23. 0 3
      CamelotRenderer/Include/CmGpuProgramManager.h
  24. 1 1
      CamelotRenderer/Include/CmHighLevelGpuProgram.h
  25. 0 3
      CamelotRenderer/Include/CmHighLevelGpuProgramManager.h
  26. 1 1
      CamelotRenderer/Include/CmRenderSystem.h
  27. 11 3
      CamelotRenderer/Source/CmApplication.cpp
  28. 1 12
      CamelotRenderer/Source/CmGpuProgramManager.cpp
  29. 3 8
      CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp
  30. 22 17
      CamelotRenderer/Source/CmRenderSystem.cpp
  31. 4 1
      CamelotRenderer/Source/CmWindowEventUtilities.cpp
  32. 23 2
      CamelotRenderer/TODO.txt

+ 55 - 49
CamelotClient/CamelotClient.cpp

@@ -2,6 +2,7 @@
 //
 
 #include "stdafx.h"
+#include <windows.h>
 
 #include "CmApplication.h"
 #include "CmDynLibManager.h"
@@ -24,10 +25,15 @@
 
 using namespace CamelotEngine;
 
-int _tmain(int argc, _TCHAR* argv[])
+int CALLBACK WinMain(
+	_In_  HINSTANCE hInstance,
+	_In_  HINSTANCE hPrevInstance,
+	_In_  LPSTR lpCmdLine,
+	_In_  int nCmdShow
+	)
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
 	//gApplication().startUp("CamelotD3D11RenderSystem", "CamelotForwardRenderer");
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
@@ -51,27 +57,27 @@ int _tmain(int argc, _TCHAR* argv[])
 	HighLevelGpuProgramPtr vertProg;
 
 	/////////////////// HLSL 9 SHADERS //////////////////////////
-	String fragShaderCode = "sampler2D tex;			\
-							float4 ps_main(float2 uv : TEXCOORD0) : COLOR0		\
-							{														\
-							float4 color = tex2D(tex, uv);				\
-							return color;										\
-							}";
-
-	fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-
-	String vertShaderCode = "float4x4 matViewProjection;	\
-							void vs_main(										\
-							float4 inPos : POSITION,							\
-							float2 uv : TEXCOORD0,								\
-							out float4 oPosition : POSITION,					\
-							out float2 oUv : TEXCOORD0)							\
-							{														\
-							oPosition = mul(matViewProjection, inPos);			\
-							oUv = uv;											\
-							}";
-
-	vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	//String fragShaderCode = "sampler2D tex;			\
+	//						float4 ps_main(float2 uv : TEXCOORD0) : COLOR0		\
+	//						{														\
+	//						float4 color = tex2D(tex, uv);				\
+	//						return color;										\
+	//						}";
+
+	//fragProg =  HighLevelGpuProgram::create(fragShaderCode, "ps_main", "hlsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
+
+	//String vertShaderCode = "float4x4 matViewProjection;	\
+	//						void vs_main(										\
+	//						float4 inPos : POSITION,							\
+	//						float2 uv : TEXCOORD0,								\
+	//						out float4 oPosition : POSITION,					\
+	//						out float2 oUv : TEXCOORD0)							\
+	//						{														\
+	//						oPosition = mul(matViewProjection, inPos);			\
+	//						oUv = uv;											\
+	//						}";
+
+	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "hlsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	/////////////////// HLSL 11 SHADERS //////////////////////////
 	//String fragShaderCode = "SamplerState samp : register(s0);			\
@@ -121,31 +127,31 @@ int _tmain(int argc, _TCHAR* argv[])
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	///////////////// GLSL SHADERS ////////////////////////////
-	//String fragShaderCode = " #version 400 \n \
-	//						  uniform sampler2D tex; \
-	//						  in vec2 texcoord0; \
-	//						  out vec4 fragColor; \
-	//						  void main() \
-	//						  {\
-	//							  vec4 texColor = texture2D(tex, texcoord0.st);\
-	//							  fragColor = texColor; \
-	//						  }";
-
-	//fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
-
-	//// TODO - Make sure to document the strict input parameter naming. (Exact supported names are in GLSLParamParser)
-	//String vertShaderCode = "#version 400 \n \
-	//						 uniform mainFragBlock { mat4 matViewProjection; }; \
-	//						 in vec4 cm_position; \
-	//						 in vec2 cm_texcoord0; \
-	//						 out vec2 texcoord0; \
-	//						 void main() \
-	//						 { \
-	//							texcoord0 = cm_texcoord0; \
-	//							gl_Position = cm_position * matViewProjection; \
-	//						 }";
-
-	//vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
+	String fragShaderCode = " #version 400 \n \
+							  uniform sampler2D tex; \
+							  in vec2 texcoord0; \
+							  out vec4 fragColor; \
+							  void main() \
+							  {\
+								  vec4 texColor = texture2D(tex, texcoord0.st);\
+								  fragColor = texColor; \
+							  }";
+
+	fragProg = HighLevelGpuProgram::create(fragShaderCode, "main", "glsl", GPT_FRAGMENT_PROGRAM, GPP_PS_2_0);
+
+	// TODO - Make sure to document the strict input parameter naming. (Exact supported names are in GLSLParamParser)
+	String vertShaderCode = "#version 400 \n \
+							 uniform mainFragBlock { mat4 matViewProjection; }; \
+							 in vec4 cm_position; \
+							 in vec2 cm_texcoord0; \
+							 out vec2 texcoord0; \
+							 void main() \
+							 { \
+								texcoord0 = cm_texcoord0; \
+								gl_Position = cm_position * matViewProjection; \
+							 }";
+
+	vertProg = HighLevelGpuProgram::create(vertShaderCode, "main", "glsl", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 

+ 4 - 4
CamelotClient/CamelotClient.vcxproj

@@ -97,7 +97,7 @@
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
     </ClCompile>
     <Link>
-      <SubSystem>Console</SubSystem>
+      <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>CamelotRenderer.lib;CamelotUtility.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\lib\$(Configuration);..\Dependencies\lib\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
@@ -114,7 +114,7 @@
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
     </ClCompile>
     <Link>
-      <SubSystem>Console</SubSystem>
+      <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>CamelotRenderer.lib;CamelotUtility.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalLibraryDirectories>..\lib\$(Platform)\$(Configuration);..\Dependencies\lib\x64\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
@@ -133,7 +133,7 @@
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
     </ClCompile>
     <Link>
-      <SubSystem>Console</SubSystem>
+      <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
@@ -154,7 +154,7 @@
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
     </ClCompile>
     <Link>
-      <SubSystem>Console</SubSystem>
+      <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>

+ 0 - 1
CamelotD3D11RenderSystem/Include/CmD3D11HLSLProgramFactory.h

@@ -16,6 +16,5 @@ namespace CamelotEngine
 		const String& getLanguage(void) const;
 		HighLevelGpuProgram* create(const String& source, const String& entryPoint, GpuProgramType gptype, GpuProgramProfile profile);
 		HighLevelGpuProgram* create();
-		void destroy_internal(HighLevelGpuProgram* prog);
 	};
 }

+ 0 - 5
CamelotD3D11RenderSystem/Source/CmD3D11HLSLProgramFactory.cpp

@@ -31,9 +31,4 @@ namespace CamelotEngine
 
 		return prog;
 	}
-
-	void D3D11HLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
-    {
-        delete prog;
-    }
 }

+ 2 - 1
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -43,7 +43,8 @@ namespace CamelotEngine
 
 	D3D11RenderSystem::~D3D11RenderSystem()
 	{
-		destroy_internal();
+		// This needs to be called from the child class, since destroy_internal is virtual
+		queueCommand(boost::bind(&D3D11RenderSystem::destroy_internal, this), true);
 	}
 
 	const String& D3D11RenderSystem::getName() const

+ 0 - 2
CamelotD3D9Renderer/Include/CmD3D9HLSLProgramFactory.h

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

+ 6 - 10
CamelotD3D9Renderer/Include/CmD3D9ResourceManager.h

@@ -76,6 +76,12 @@ namespace CamelotEngine {
 		// Relevant for multi thread application.
 		void unlockDeviceAccess		();
 		
+		// Called when new resource created.
+		void _notifyResourceCreated		(D3D9Resource* pResource);
+
+		// Called when resource is about to be destroyed.
+		void _notifyResourceDestroyed	(D3D9Resource* pResource);
+
 		D3D9ResourceManager			();
 		~D3D9ResourceManager		();		
 
@@ -91,16 +97,6 @@ namespace CamelotEngine {
 		typedef vector<D3D9Resource*>::type		ResourceContainer;
 		typedef ResourceContainer::iterator		ResourceContainerIterator;
 
-	// Protected methods.
-	protected:
-		
-		// Called when new resource created.
-		void _notifyResourceCreated		(D3D9Resource* pResource);
-
-		// Called when resource is about to be destroyed.
-		void _notifyResourceDestroyed	(D3D9Resource* pResource);
-				
-
 	// Attributes.
 	protected:		
 		CM_MUTEX(mResourcesMutex)

+ 0 - 2
CamelotD3D9Renderer/Source/CmD3D9Device.cpp

@@ -706,8 +706,6 @@ namespace CamelotEngine
 
 			mpDeviceManager->setActiveDevice(pCurActiveDevice);
 			
-			clearDeviceStreams();		
-
 			// Release device.
 			SAFE_RELEASE(mpDevice);	
 			

+ 3 - 0
CamelotD3D9Renderer/Source/CmD3D9GpuProgram.cpp

@@ -30,6 +30,7 @@ THE SOFTWARE.
 #include "CmException.h"
 #include "CmD3D9Mappings.h"
 #include "CmD3D9RenderSystem.h"
+#include "CmD3D9ResourceManager.h"
 #include "CmGpuParams.h"
 #include "CmAsyncOp.h"
 
@@ -291,6 +292,8 @@ namespace CamelotEngine {
 		}
 		mMapDeviceToPixelShader.clear();	
 
+		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+
 		D3D9GpuProgram::destroy_internal();
     }
 	//-----------------------------------------------------------------------------

+ 0 - 6
CamelotD3D9Renderer/Source/CmD3D9HLSLProgramFactory.cpp

@@ -60,10 +60,4 @@ namespace CamelotEngine {
 
 		return prog;
 	}
-    //-----------------------------------------------------------------------
-	void D3D9HLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
-    {
-        delete prog;
-    }
-    //-----------------------------------------------------------------------
 }

+ 2 - 0
CamelotD3D9Renderer/Source/CmD3D9IndexBuffer.cpp

@@ -341,6 +341,8 @@ namespace CamelotEngine {
 		mMapDeviceToBufferResources.clear();   
 		SAFE_DELETE_ARRAY(mSystemMemoryBuffer);
 
+		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+
 		IndexBuffer::destroy_internal();
 	}
 }

+ 23 - 26
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -116,28 +116,9 @@ namespace CamelotEngine
 	}
 	//---------------------------------------------------------------------
 	D3D9RenderSystem::~D3D9RenderSystem()
-	{		
-		destroy_internal();
-
-		// Deleting the HLSL program factory
-		if (mHLSLProgramFactory)
-		{
-			HighLevelGpuProgramManager::instance().removeFactory(mHLSLProgramFactory);
-			delete mHLSLProgramFactory;
-			mHLSLProgramFactory = 0;
-		}
-
-		if(mCgProgramFactory)
-		{
-			HighLevelGpuProgramManager::instance().removeFactory(mCgProgramFactory);
-			delete mCgProgramFactory;
-			mCgProgramFactory = 0;
-		}
-
-		SAFE_RELEASE( mpD3D );
-		SAFE_DELETE ( mResourceManager );
-
-		msD3D9RenderSystem = NULL;
+	{
+		// This needs to be called from the child class, since destroy_internal is virtual
+		queueCommand(boost::bind(&D3D9RenderSystem::destroy_internal, this), true);
 	}
 
 	const String& D3D9RenderSystem::getName() const
@@ -225,6 +206,26 @@ namespace CamelotEngine
 		GpuProgramManager::shutDown();	
 		RenderWindowManager::shutDown();
 		RenderStateManager::shutDown();
+
+		// Deleting the HLSL program factory
+		if (mHLSLProgramFactory)
+		{
+			HighLevelGpuProgramManager::instance().removeFactory(mHLSLProgramFactory);
+			delete mHLSLProgramFactory;
+			mHLSLProgramFactory = 0;
+		}
+
+		if(mCgProgramFactory)
+		{
+			HighLevelGpuProgramManager::instance().removeFactory(mCgProgramFactory);
+			delete mCgProgramFactory;
+			mCgProgramFactory = 0;
+		}
+
+		SAFE_RELEASE( mpD3D );
+		SAFE_DELETE ( mResourceManager );
+
+		msD3D9RenderSystem = NULL;
 	}
 	//--------------------------------------------------------------------
 	void D3D9RenderSystem::registerRenderWindow(D3D9RenderWindowPtr renderWindow)
@@ -1171,10 +1172,6 @@ namespace CamelotEngine
 			CM_EXCEPT(RenderingAPIException, "Error beginning frame :" + msg);
 		}
 
-		// Clear left overs of previous viewport.
-		// I.E: Viewport A can use 3 different textures and light states
-		// When trying to render viewport B these settings should be cleared, otherwise 
-		// graphical artifacts might occur.
  		mDeviceManager->getActiveDevice()->clearDeviceStreams();
 	}
 	//---------------------------------------------------------------------

+ 1 - 1
CamelotD3D9Renderer/Source/CmD3D9Resource.cpp

@@ -40,7 +40,7 @@ namespace CamelotEngine
 
 	D3D9Resource::~D3D9Resource()
 	{		
-		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+		
 	}
 	
 	void D3D9Resource::lockDeviceAccess()

+ 20 - 20
CamelotD3D9Renderer/Source/CmD3D9ResourceManager.cpp

@@ -60,53 +60,53 @@ namespace CamelotEngine
 	 //-----------------------------------------------------------------------
 	void D3D9ResourceManager::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
 	{				
-		CM_LOCK_MUTEX(mResourcesMutex)
+/*		CM_LOCK_MUTEX(mResourcesMutex)
 
 		ResourceContainerIterator it = mResources.begin();
 		while (it != mResources.end())
 		{
 			(*it)->notifyOnDeviceCreate(d3d9Device);
 			++it;
-		}				
+		}		*/		
 	}
 
 	 //-----------------------------------------------------------------------
 	void D3D9ResourceManager::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
 	{
-		CM_LOCK_MUTEX(mResourcesMutex)
-
-		ResourceContainerIterator it = mResources.begin();
-		while (it != mResources.end())
-		{
-			(*it)->notifyOnDeviceDestroy(d3d9Device);
-			++it;
-		}	
+		//CM_LOCK_MUTEX(mResourcesMutex)
+
+		//ResourceContainerIterator it = mResources.begin();
+		//while (it != mResources.end())
+		//{
+		//	(*it)->notifyOnDeviceDestroy(d3d9Device);
+		//	++it;
+		//}	
 	}
 
 	 //-----------------------------------------------------------------------
 	void D3D9ResourceManager::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
 	{
-		CM_LOCK_MUTEX(mResourcesMutex)
-
-		ResourceContainerIterator it = mResources.begin();
-		while (it != mResources.end())
-		{
-			(*it)->notifyOnDeviceLost(d3d9Device);
-			++it;
-		}	
+		//CM_LOCK_MUTEX(mResourcesMutex)
+
+		//ResourceContainerIterator it = mResources.begin();
+		//while (it != mResources.end())
+		//{
+		//	(*it)->notifyOnDeviceLost(d3d9Device);
+		//	++it;
+		//}	
 	}
 
 	 //-----------------------------------------------------------------------
 	void D3D9ResourceManager::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
 	{		
-		CM_LOCK_MUTEX(mResourcesMutex)
+/*		CM_LOCK_MUTEX(mResourcesMutex)
 
 		ResourceContainerIterator it = mResources.begin();
 		while (it != mResources.end())
 		{
 			(*it)->notifyOnDeviceReset(d3d9Device);
 			++it;			
-		}		
+		}	*/	
 	}
 
 	//-----------------------------------------------------------------------

+ 2 - 0
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -240,6 +240,8 @@ namespace CamelotEngine
 		
 		clearBufferViews();
 
+		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+
 		IDestroyable::destroy();
 	}
 	/****************************************************************************************/

+ 2 - 0
CamelotD3D9Renderer/Source/CmD3D9VertexBuffer.cpp

@@ -340,6 +340,8 @@ namespace CamelotEngine {
 		mMapDeviceToBufferResources.clear();   
 		SAFE_DELETE_ARRAY(mSystemMemoryBuffer);
 
+		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+
 		VertexBuffer::destroy_internal();
 	}
 }

+ 3 - 0
CamelotD3D9Renderer/Source/CmD3D9VertexDeclaration.cpp

@@ -29,6 +29,7 @@ THE SOFTWARE.
 #include "CmD3D9Mappings.h"
 #include "CmException.h"
 #include "CmD3D9RenderSystem.h"
+#include "CmD3D9ResourceManager.h"
 
 namespace CamelotEngine {
 
@@ -188,6 +189,8 @@ namespace CamelotEngine {
 	{
 		releaseDeclaration();
 
+		D3D9RenderSystem::getResourceManager()->_notifyResourceDestroyed(static_cast<D3D9Resource*>(this));
+
 		VertexDeclaration::destroy_internal();
 	}
 }

+ 17 - 16
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -124,21 +124,8 @@ namespace CamelotEngine
 
 	GLRenderSystem::~GLRenderSystem()
 	{
-		destroy_internal();
-
-		if(mProgramPipelineManager != nullptr)
-			delete mProgramPipelineManager;
-
-		// Destroy render windows
-		for (auto i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i)
-		{
-			delete *i;
-		}
-
-		mRenderTargets.clear();
-
-        if(mGLSupport)
-            delete mGLSupport;
+		// This needs to be called from the child class, since destroy_internal is virtual
+		queueCommand(boost::bind(&GLRenderSystem::destroy_internal, this), true);
 	}
 
 	const String& GLRenderSystem::getName(void) const
@@ -166,7 +153,7 @@ namespace CamelotEngine
 		RenderSystem::initialize_internal();
 	}
 
-	void GLRenderSystem::destroy_internal(void)
+	void GLRenderSystem::destroy_internal()
 	{
 		RenderSystem::destroy_internal();
 
@@ -220,6 +207,20 @@ namespace CamelotEngine
 		//  some params will access an invalid pointer, so it is best to reset
 		//  the whole state.
 		mGLInitialised = 0;
+
+		if(mProgramPipelineManager != nullptr)
+			delete mProgramPipelineManager;
+
+		// Destroy render windows
+		for (auto i = mRenderTargets.begin(); i != mRenderTargets.end(); ++i)
+		{
+			delete *i;
+		}
+
+		mRenderTargets.clear();
+
+		if(mGLSupport)
+			delete mGLSupport;
 	}
 
 	//---------------------------------------------------------------------

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

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

+ 0 - 7
CamelotGLRenderer/Source/GLSL/src/CmGLSLProgramFactory.cpp

@@ -51,11 +51,4 @@ namespace CamelotEngine {
 
 		return prog;
 	}
-    //-----------------------------------------------------------------------
-	void GLSLProgramFactory::destroy_internal(HighLevelGpuProgram* prog)
-    {
-        delete prog;
-    }
-    //-----------------------------------------------------------------------
-
 }

+ 23 - 0
CamelotRenderer/Include/CmApplication.h

@@ -18,8 +18,29 @@ namespace CamelotEngine
 		public:
 			Application();
 
+			/**
+			 * @brief	Starts the application using the specified options. 
+			 * 			This is how you start the engine.
+			 */
 			void startUp(const String& renderSystemDll, const String& rendererDll);
+
+			/**
+			 * @brief	Executes the main loop. This will cause actually rendering to be performed
+			 * 			and simulation to be run. Usually called immediately after startUp().
+			 * 			
+			 *			This will run infinitely until stopMainLoop is called (usually from another thread or internally).
+			 */
 			void runMainLoop();
+
+			/**
+			 * @brief	Stops a (infinite) main loop from running. The loop will complete its current cycle before stopping.
+			 * 			You may call this from other threads.
+			 */
+			void stopMainLoop();
+
+			/**
+			 * @brief	Frees up all resources allocated during startUp, and while the application was running.
+			 */
 			void shutDown();
 
 			UINT64 getAppWindowId();
@@ -43,6 +64,8 @@ namespace CamelotEngine
 		bool mIsFrameRenderingFinished;
 		CM_MUTEX(mFrameRenderingFinishedMutex);
 
+		volatile bool mRunMainLoop;
+
 		/**
 		 * @brief	Callback called from the render thread in order to initialize resources.
 		 */

+ 0 - 1
CamelotRenderer/Include/CmCommandQueue.h

@@ -112,7 +112,6 @@ namespace CamelotEngine
 	private:
 		vector<Command>::type* mCommands;
 
-		bool mIsShutdown;
 		bool mAllowAllThreads;
 
 		CM_THREAD_ID_TYPE mMyThreadId;

+ 0 - 3
CamelotRenderer/Include/CmGpuProgramManager.h

@@ -53,9 +53,6 @@ namespace CamelotEngine {
         */
         virtual GpuProgram* create(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile) = 0;
 
-		void destroy(GpuProgram* program);
-		virtual void destroy_internal(GpuProgram* program);
-
 	public:
 		GpuProgramManager();
 		virtual ~GpuProgramManager();

+ 1 - 1
CamelotRenderer/Include/CmHighLevelGpuProgram.h

@@ -63,7 +63,7 @@ namespace CamelotEngine {
     class CM_EXPORT HighLevelGpuProgram : public GpuProgram
     {
     public:
-        ~HighLevelGpuProgram();
+        virtual ~HighLevelGpuProgram();
 
 		/** @copydoc GpuProgram::initialize_internal(). */
 		virtual void initialize_internal();

+ 0 - 3
CamelotRenderer/Include/CmHighLevelGpuProgramManager.h

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

+ 1 - 1
CamelotRenderer/Include/CmRenderSystem.h

@@ -449,7 +449,7 @@ namespace CamelotEngine
 		};
 
 		RenderWorkerFunc* mRenderThreadFunc;
-		bool mRenderThreadShutdown;
+		volatile bool mRenderThreadShutdown;
 
 		CM_THREAD_ID_TYPE mRenderThreadId;
 		CM_THREAD_SYNCHRONISER(mRenderThreadStartCondition)

+ 11 - 3
CamelotRenderer/Source/CmApplication.cpp

@@ -34,7 +34,7 @@
 namespace CamelotEngine
 {
 	Application::Application()
-		:mPrimaryRenderWindow(nullptr), mIsFrameRenderingFinished(true)
+		:mPrimaryRenderWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false)
 	{ }
 
 	void Application::startUp(const String& renderSystemName, const String& rendererName)
@@ -72,7 +72,9 @@ namespace CamelotEngine
 
 	void Application::runMainLoop()
 	{
-		while(true)
+		mRunMainLoop = true;
+
+		while(mRunMainLoop)
 		{
 			gSceneManager().update();
 
@@ -108,6 +110,12 @@ namespace CamelotEngine
 		}
 	}
 
+	void Application::stopMainLoop()
+	{
+		mRunMainLoop = false; // No sync primitives needed, in that rare case of 
+		// a race condition we might run the loop one extra iteration which is acceptable
+	}
+
 	void Application::updateMessagePump()
 	{
 		WindowEventUtilities::messagePump();
@@ -131,7 +139,7 @@ namespace CamelotEngine
 		RenderSystem::shutDown();
 
 		HighLevelGpuProgramManager::shutDown();
-		DynLibManager::shutDown();
+		//DynLibManager::shutDown();
 		Resources::shutDown();
 		Input::shutDown();
 		Time::shutDown();

+ 1 - 12
CamelotRenderer/Source/CmGpuProgramManager.cpp

@@ -41,21 +41,10 @@ namespace CamelotEngine {
 	{
 		// subclasses should unregister with resource group manager
 	}
-	//-------------------------------------------------------------------------
-	void GpuProgramManager::destroy(GpuProgram* program)
-	{
-		RenderSystem::instancePtr()->queueCommand(boost::bind(&GpuProgramManager::destroy_internal, this, program));
-	}
-	//-------------------------------------------------------------------------
-	void GpuProgramManager::destroy_internal(GpuProgram* program)
-	{
-		if(program != nullptr)
-			delete program;
-	}
     //---------------------------------------------------------------------------
 	GpuProgramPtr GpuProgramManager::createProgram(const String& source, const String& entryPoint, const String& language, GpuProgramType gptype, GpuProgramProfile profile)
     {
-		GpuProgramPtr prg = GpuProgramPtr(create(source, entryPoint, language, gptype, profile), boost::bind(&GpuProgramManager::destroy, this, _1));
+		GpuProgramPtr prg = GpuProgramPtr(create(source, entryPoint, language, gptype, profile));
 
         return prg;
     }

+ 3 - 8
CamelotRenderer/Source/CmHighLevelGpuProgramManager.cpp

@@ -132,11 +132,6 @@ namespace CamelotEngine {
 		}
 		return i->second;
 	}
-	//---------------------------------------------------------------------------
-	void HighLevelGpuProgramFactory::destroy(HighLevelGpuProgram* prog)
-	{
-		RenderSystem::instancePtr()->queueCommand(boost::bind(&HighLevelGpuProgramFactory::destroy_internal, this, prog));
-	}
 	//---------------------------------------------------------------------
 	bool HighLevelGpuProgramManager::isLanguageSupported(const String& lang)
 	{
@@ -150,7 +145,7 @@ namespace CamelotEngine {
 		GpuProgramType gptype, GpuProgramProfile profile)
     {
 		HighLevelGpuProgramFactory* factory = getFactory(language);
-        HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(source, entryPoint, gptype, profile), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
+        HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(source, entryPoint, gptype, profile));
 		ret->initialize();
 
         return ret;
@@ -159,7 +154,7 @@ namespace CamelotEngine {
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::create(const String& language)
 	{
 		HighLevelGpuProgramFactory* factory = getFactory(language);
-		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
+		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create());
 		ret->initialize();
 
 		return ret;
@@ -168,7 +163,7 @@ namespace CamelotEngine {
 	HighLevelGpuProgramPtr HighLevelGpuProgramManager::createEmpty(const String& language)
 	{
 		HighLevelGpuProgramFactory* factory = getFactory(language);
-		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create(), boost::bind(&HighLevelGpuProgramFactory::destroy, factory, _1));
+		HighLevelGpuProgramPtr ret = HighLevelGpuProgramPtr(factory->create());
 
 		return ret;
 	}

+ 22 - 17
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -76,10 +76,17 @@ namespace CamelotEngine {
     //-----------------------------------------------------------------------
     RenderSystem::~RenderSystem()
     {
-		queueCommand(boost::bind(&RenderSystem::destroy_internal, this), true);
-		// TODO - What if something gets queued between these two calls?
+		// Base classes need to call virtual destroy_internal method (queue it on render thread)
+
+		// TODO - What if something gets queued between the queued call to destroy_internal and this!?
 		shutdownRenderThread();
 
+		if(mCommandQueue != nullptr)
+		{
+			delete mCommandQueue;
+			mCommandQueue = nullptr;
+		}
+
 		delete mCurrentCapabilities;
 		mCurrentCapabilities = 0;
     }
@@ -103,10 +110,8 @@ namespace CamelotEngine {
 		mFragmentProgramBound = false;
 	}
 	//-----------------------------------------------------------------------
-	void RenderSystem::destroy_internal(void)
+	void RenderSystem::destroy_internal()
 	{
-		// TODO - I should probably sync this up to make sure no other threads are doing anything while shutdown is in progress
-
 		// Remove all the render targets.
 		// (destroy primary target last since others may depend on it)
 		RenderTarget* primary = 0;
@@ -121,12 +126,6 @@ namespace CamelotEngine {
 		mRenderTargets.clear();
 
 		mPrioritisedRenderTargets.clear();
-
-		if(mCommandQueue != nullptr)
-		{
-			delete mCommandQueue;
-			mCommandQueue = nullptr;
-		}
 	}
     //-----------------------------------------------------------------------
     void RenderSystem::swapAllRenderTargetBuffers(bool waitForVSync)
@@ -405,16 +404,18 @@ namespace CamelotEngine {
 
 		while(true)
 		{
-			if(mRenderThreadShutdown)
-				return;
-
 			// Wait until we get some ready commands
 			vector<CommandQueue::Command>::type* commands = nullptr;
 			{
 				CM_LOCK_MUTEX_NAMED(mCommandQueueMutex, lock)
 
 				while(mCommandQueue->isEmpty())
-					CM_THREAD_WAIT(mCommandReadyCondition, mCommandQueueMutex, lock)
+				{
+					if(mRenderThreadShutdown)
+						return;
+
+					CM_THREAD_WAIT(mCommandReadyCondition, mCommandQueueMutex, lock);
+				}
 
 				commands = mCommandQueue->flush();
 			}
@@ -428,10 +429,14 @@ namespace CamelotEngine {
 	void RenderSystem::shutdownRenderThread()
 	{
 #if !CM_FORCE_SINGLETHREADED_RENDERING
-		mRenderThreadShutdown = true;
+
+		{
+			CM_LOCK_MUTEX(mCommandQueueMutex);
+			mRenderThreadShutdown = true;
+		}
 
 		// Wake all threads. They will quit after they see the shutdown flag
-		CM_THREAD_NOTIFY_ALL(mCommandReadyCondition)
+		CM_THREAD_NOTIFY_ALL(mCommandReadyCondition);
 
 		mRenderThread->join();
 		CM_THREAD_DESTROY(mRenderThread);

+ 4 - 1
CamelotRenderer/Source/CmWindowEventUtilities.cpp

@@ -27,6 +27,7 @@ THE SOFTWARE.
 */
 #include "CmWindowEventUtilities.h"
 #include "CmRenderWindow.h"
+#include "CmApplication.h"
 #include "CmException.h"
 #if CM_PLATFORM == CM_PLATFORM_LINUX
 #include <X11/Xlib.h>
@@ -241,7 +242,9 @@ LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wPa
 
 		for(index = _msListeners.lower_bound(win); index != end; ++index)
 			(index->second)->windowClosed(win);
-		win->destroy();
+
+		gApplication().stopMainLoop();
+
 		return 0;
 	}
 	}

+ 23 - 2
CamelotRenderer/TODO.txt

@@ -50,9 +50,25 @@ Stuff that needs destroy():
   - Shader
   - Technique
 
-Calling destroy() and then immediately releasing last reference to an object will delete the object before it is destroyed. (Since destroy()) gets queued.
+I am currently completely ignoring D3D9ResourceManager. It is not notified when a resource is destroyed (actually destructed), 
+so it's mResources array contains many invalid pointers. Normally resource was removed from that list whenever it was 
+destructed but with my current approach, that might be AFTER the render system is shut down, which doesn't work. I need to 
+figure out a better way of releasing all resources when the application shuts down so that this doesn't happen.
+
+Plan today & saturday:
+ Add destroy() for remaining classes
+ Handle the issue with destroy() and immediately releasing object reference before destroy gets executed()
+
+ - Support loading of compound objects:
+   - Loading Material also loads attached Shader and Textures/Samplers
+  - Make Resources::destroy() private
+  - Have Resources::unload which calls destroy() internally
+  - Have Resources::unloadUnused() which unloads all with reference count of 1
+
 
-Upon calling destroy() I should keep a temporary reference to the object until it actually is destroyed.
+
+Calling destroy() and then immediately releasing last reference to an object will delete the object before it is destroyed. (Since destroy()) gets queued.
+ - Upon calling destroy() I should keep a temporary reference to the object until it actually is destroyed.
 
 Material RTTI should also serialize shared buffers (they need to be made into a resource)
  - BE CAREFUL on how this will be implemented. Likely it will have much of the same interface as a material and/or GpuParams
@@ -148,6 +164,11 @@ Command buffer TODO:
     that call.
  - In general I need to rethink how to handle modifying resources with multithreading
 
+Editor IMPORTANT:
+ - When displaying inspector data for a component, take into consideration that it will need to be able
+    to display that data for user created C# classes as well. AND I will most certainly have C# versions of all my
+	components. Therefore is there any purpose of having C++ only inspector parsing code?
+
 -----------------------BACKLOG TODO---------------------------------------------------------------
 
 HIGH PRIORITY TODO: