Browse Source

Fixed an issue with simulation running much faster than the render thread and causing massive input lag

Marko Pintera 13 years ago
parent
commit
b2442bedf0

+ 48 - 48
CamelotClient/CamelotClient.cpp

@@ -26,8 +26,8 @@ using namespace CamelotEngine;
 
 
 int _tmain(int argc, _TCHAR* argv[])
 int _tmain(int argc, _TCHAR* argv[])
 {
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
 
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
@@ -50,27 +50,27 @@ int _tmain(int argc, _TCHAR* argv[])
 	HighLevelGpuProgramPtr vertProg;
 	HighLevelGpuProgramPtr vertProg;
 
 
 	/////////////////// HLSL SHADERS //////////////////////////
 	/////////////////// HLSL 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);
 
 
 	/////////////////// CG SHADERS //////////////////////////
 	/////////////////// CG SHADERS //////////////////////////
 	//String fragShaderCode = "sampler2D tex;					\
 	//String fragShaderCode = "sampler2D tex;					\
@@ -96,31 +96,31 @@ int _tmain(int argc, _TCHAR* argv[])
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 	//vertProg =  HighLevelGpuProgram::create(vertShaderCode, "vs_main", "cg", GPT_VERTEX_PROGRAM, GPP_VS_2_0);
 
 
 	///////////////// GLSL SHADERS ////////////////////////////
 	///////////////// 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);
 	HighLevelGpuProgramHandle vertProgRef(vertProg);
 
 

+ 5 - 0
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

@@ -443,6 +443,11 @@ namespace CamelotEngine
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
+		// Don't forget to clear all render targets if its a multi render target
+		
+
+
+
 		//target->g
 		//target->g
 
 
 		//RenderTarget* previousRenderTarget = mActiveRenderTarget;
 		//RenderTarget* previousRenderTarget = mActiveRenderTarget;

+ 8 - 0
CamelotRenderer/Include/CmApplication.h

@@ -40,6 +40,9 @@ namespace CamelotEngine
 		RenderWindowPtr mPrimaryRenderWindow;
 		RenderWindowPtr mPrimaryRenderWindow;
 		DeferredRenderContextPtr mPrimaryRenderContext;
 		DeferredRenderContextPtr mPrimaryRenderContext;
 
 
+		bool mIsFrameRenderingFinished;
+		CM_MUTEX(mFrameRenderingFinishedMutex);
+
 		/**
 		/**
 		 * @brief	Callback called from the render thread in order to initialize resources.
 		 * @brief	Callback called from the render thread in order to initialize resources.
 		 */
 		 */
@@ -49,6 +52,11 @@ namespace CamelotEngine
 		 * @brief	Runs the OS specific message pump.
 		 * @brief	Runs the OS specific message pump.
 		 */
 		 */
 		void updateMessagePump();
 		void updateMessagePump();
+
+		/**
+		 * @brief	Called when the frame finishes rendering.
+		 */
+		void frameRenderingFinishedCallback();
 	};
 	};
 
 
 	CM_EXPORT Application& gApplication();
 	CM_EXPORT Application& gApplication();

+ 5 - 0
CamelotRenderer/Include/CmDeferredRenderContext.h

@@ -108,6 +108,11 @@ namespace CamelotEngine
 		 */
 		 */
 		void submitToGpu();
 		void submitToGpu();
 
 
+		/**
+		 * @brief	Cancels all commands in the queue.
+		 */
+		void cancelAll();
+
 	private:
 	private:
 		CommandQueue* mCommandQueue;
 		CommandQueue* mCommandQueue;
 		RenderSystem* mRenderSystem;
 		RenderSystem* mRenderSystem;

+ 32 - 5
CamelotRenderer/Source/CmApplication.cpp

@@ -34,7 +34,7 @@
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
 	Application::Application()
 	Application::Application()
-		:mPrimaryRenderWindow(nullptr)
+		:mPrimaryRenderWindow(nullptr), mIsFrameRenderingFinished(true)
 	{ }
 	{ }
 
 
 	void Application::startUp(const String& renderSystemName, const String& rendererName)
 	void Application::startUp(const String& renderSystemName, const String& rendererName)
@@ -77,11 +77,31 @@ namespace CamelotEngine
 			gSceneManager().update();
 			gSceneManager().update();
 
 
 			RenderSystem* renderSystem = RenderSystem::instancePtr();
 			RenderSystem* renderSystem = RenderSystem::instancePtr();
-			renderSystem->queueCommand(boost::bind(&Application::updateMessagePump, this));
-			renderSystem->queueCommand(boost::bind(&Application::updateResourcesCallback, this));
-
 			RendererManager::getActive()->renderAll();
 			RendererManager::getActive()->renderAll();
-			mPrimaryRenderContext->submitToGpu();
+
+			// Only queue new commands if render thread has finished rendering
+			// TODO - There might be a more optimal way to sync simulation and render threads so we maximize
+			// the amount of rendered frames
+			bool readyForNextFrame = false;
+			{
+				CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
+				readyForNextFrame = mIsFrameRenderingFinished;
+			}
+
+			if(readyForNextFrame)
+			{
+				{
+					CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
+					mIsFrameRenderingFinished = false;
+				}
+				
+				renderSystem->queueCommand(boost::bind(&Application::updateMessagePump, this));
+				renderSystem->queueCommand(boost::bind(&Application::updateResourcesCallback, this));
+				mPrimaryRenderContext->submitToGpu();
+				renderSystem->queueCommand(boost::bind(&Application::frameRenderingFinishedCallback, this));
+			}
+			else
+				mPrimaryRenderContext->cancelAll();
 
 
 			gTime().update();
 			gTime().update();
 			gInput().update();
 			gInput().update();
@@ -98,6 +118,13 @@ namespace CamelotEngine
 		gResources().update();
 		gResources().update();
 	}
 	}
 
 
+	void Application::frameRenderingFinishedCallback()
+	{
+		CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
+
+		mIsFrameRenderingFinished = true;
+	}
+
 	void Application::shutDown()
 	void Application::shutDown()
 	{
 	{
 		SceneManager::shutDown();
 		SceneManager::shutDown();

+ 7 - 0
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -175,4 +175,11 @@ namespace CamelotEngine
 		RenderSystem* rs = RenderSystem::instancePtr();
 		RenderSystem* rs = RenderSystem::instancePtr();
 		rs->queueCommand(boost::bind(&CommandQueue::playback, mCommandQueue, commands));
 		rs->queueCommand(boost::bind(&CommandQueue::playback, mCommandQueue, commands));
 	}
 	}
+
+	void DeferredRenderContext::cancelAll()
+	{
+		vector<CommandQueue::Command>::type* commands = mCommandQueue->flush();
+
+		// TODO - This cancels the commands but doesn't revert the state variables
+	}
 }
 }

+ 1 - 3
CamelotRenderer/TODO.txt

@@ -33,8 +33,6 @@
  Think about how to manage resources. For example check VertexBuffer is VertexData class. How and when is that freed?
  Think about how to manage resources. For example check VertexBuffer is VertexData class. How and when is that freed?
  - Big problem is also that RenderSystem in a lot of cases holds raw pointers, so what happens when resource get destroyed and RS tries to use it?
  - Big problem is also that RenderSystem in a lot of cases holds raw pointers, so what happens when resource get destroyed and RS tries to use it?
 
 
-Extreme lag when starting the game with OpenGL!?
-
 >>>>>>>>>>>>>>>START WORKING ON THE EDITOR!
 >>>>>>>>>>>>>>>START WORKING ON THE EDITOR!
  
  
 
 
@@ -73,7 +71,6 @@ RenderSystem needed modifications
 
 
 Command buffer TODO:
 Command buffer TODO:
  - Make CommandQueue not use mutexes and use atomics instead??
  - Make CommandQueue not use mutexes and use atomics instead??
- - Make sure that the simulation can't run faster then the render thread! (Block the main thread until previous render finishes)
  - Figure out how to handle accessing texture from a non-render thread?
  - Figure out how to handle accessing texture from a non-render thread?
  - When importing a resource, and registering it with Resources I don't think it properly gets added to the loaded resources array? For some reason shaders get created twice.
  - When importing a resource, and registering it with Resources I don't think it properly gets added to the loaded resources array? For some reason shaders get created twice.
  - Doing setPixels_async in the texture doesn't make sure that the user doesn't actually modify the provided PixelData after
  - Doing setPixels_async in the texture doesn't make sure that the user doesn't actually modify the provided PixelData after
@@ -130,6 +127,7 @@ Low priority TODO:
    - Add documentation that tells the user that reading a resource non-async will block the thread and execute all queued render commands first
    - Add documentation that tells the user that reading a resource non-async will block the thread and execute all queued render commands first
    - Remove Response handlers from Resources
    - Remove Response handlers from Resources
 - Cg doesn't work. Either remove it or get it to work
 - Cg doesn't work. Either remove it or get it to work
+- System is not yet ready for multiple rendering contexts
 
 
 Optional TODO:
 Optional TODO:
  - Add precompiled headers to all projects
  - Add precompiled headers to all projects