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

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

Marko Pintera 13 лет назад
Родитель
Сommit
fda3ca2150
32 измененных файлов с 229 добавлено и 203 удалено
  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: