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[])
 {
-	//gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
-	gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
+	gApplication().startUp("CamelotGLRenderSystem", "CamelotForwardRenderer");
+	//gApplication().startUp("CamelotD3D9RenderSystem", "CamelotForwardRenderer");
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
 	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
@@ -50,27 +50,27 @@ int _tmain(int argc, _TCHAR* argv[])
 	HighLevelGpuProgramPtr vertProg;
 
 	/////////////////// 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 //////////////////////////
 	//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);
 
 	///////////////// 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);
 

+ 5 - 0
CamelotD3D11RenderSystem/Source/CmD3D11RenderSystem.cpp

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

+ 8 - 0
CamelotRenderer/Include/CmApplication.h

@@ -40,6 +40,9 @@ namespace CamelotEngine
 		RenderWindowPtr mPrimaryRenderWindow;
 		DeferredRenderContextPtr mPrimaryRenderContext;
 
+		bool mIsFrameRenderingFinished;
+		CM_MUTEX(mFrameRenderingFinishedMutex);
+
 		/**
 		 * @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.
 		 */
 		void updateMessagePump();
+
+		/**
+		 * @brief	Called when the frame finishes rendering.
+		 */
+		void frameRenderingFinishedCallback();
 	};
 
 	CM_EXPORT Application& gApplication();

+ 5 - 0
CamelotRenderer/Include/CmDeferredRenderContext.h

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

+ 32 - 5
CamelotRenderer/Source/CmApplication.cpp

@@ -34,7 +34,7 @@
 namespace CamelotEngine
 {
 	Application::Application()
-		:mPrimaryRenderWindow(nullptr)
+		:mPrimaryRenderWindow(nullptr), mIsFrameRenderingFinished(true)
 	{ }
 
 	void Application::startUp(const String& renderSystemName, const String& rendererName)
@@ -77,11 +77,31 @@ namespace CamelotEngine
 			gSceneManager().update();
 
 			RenderSystem* renderSystem = RenderSystem::instancePtr();
-			renderSystem->queueCommand(boost::bind(&Application::updateMessagePump, this));
-			renderSystem->queueCommand(boost::bind(&Application::updateResourcesCallback, this));
-
 			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();
 			gInput().update();
@@ -98,6 +118,13 @@ namespace CamelotEngine
 		gResources().update();
 	}
 
+	void Application::frameRenderingFinishedCallback()
+	{
+		CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
+
+		mIsFrameRenderingFinished = true;
+	}
+
 	void Application::shutDown()
 	{
 		SceneManager::shutDown();

+ 7 - 0
CamelotRenderer/Source/CmDeferredRenderContext.cpp

@@ -175,4 +175,11 @@ namespace CamelotEngine
 		RenderSystem* rs = RenderSystem::instancePtr();
 		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?
  - 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!
  
 
@@ -73,7 +71,6 @@ RenderSystem needed modifications
 
 Command buffer TODO:
  - 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?
  - 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
@@ -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
    - Remove Response handlers from Resources
 - Cg doesn't work. Either remove it or get it to work
+- System is not yet ready for multiple rendering contexts
 
 Optional TODO:
  - Add precompiled headers to all projects