Selaa lähdekoodia

Made sim & core thread run in lockstep

Marko Pintera 12 vuotta sitten
vanhempi
sitoutus
cc20378a61
3 muutettua tiedostoa jossa 18 lisäystä ja 19 poistoa
  1. 1 0
      CamelotCore/Include/CmApplication.h
  2. 14 19
      CamelotCore/Source/CmApplication.cpp
  3. 3 0
      TODO.txt

+ 1 - 0
CamelotCore/Include/CmApplication.h

@@ -87,6 +87,7 @@ namespace CamelotFramework
 
 		bool mIsFrameRenderingFinished;
 		CM_MUTEX(mFrameRenderingFinishedMutex);
+		CM_THREAD_SYNCHRONISER(mFrameRenderingFinishedCondition);
 
 		volatile bool mRunMainLoop;
 

+ 14 - 19
CamelotCore/Source/CmApplication.cpp

@@ -99,28 +99,22 @@ namespace CamelotFramework
 
 			RendererManager::instance().getActive()->renderAll();
 
-			// Only queue new commands if core thread has finished rendering
-			// TODO - There might be a more optimal way to sync simulation and core threads so we maximize
-			// the amount of rendered frames
-			bool readyForNextFrame = false;
+			// Core and sim thread run in lockstep. This will result in a larger input latency than if I was 
+			// running just a single thread. Latency becomes worse if the core thread takes longer than sim 
+			// thread, in which case sim thread needs to wait. Optimal solution would be to get an average 
+			// difference between sim/core thread and start the sim thread a bit later so they finish at nearly the same time.
 			{
-				CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
-				readyForNextFrame = mIsFrameRenderingFinished;
-			}
+				CM_LOCK_MUTEX_NAMED(mFrameRenderingFinishedMutex, lock);
 
-			if(readyForNextFrame)
-			{
-				{
-					CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
-					mIsFrameRenderingFinished = false;
-				}
-				
-				gCoreThread().queueCommand(boost::bind(&Application::updateMessagePump, this));
-				mPrimaryCoreAccessor->submitToCoreThread();
-				gCoreThread().queueCommand(boost::bind(&Application::frameRenderingFinishedCallback, this));
+				while(!mIsFrameRenderingFinished)
+					CM_THREAD_WAIT(mFrameRenderingFinishedCondition, mFrameRenderingFinishedMutex, lock);
+
+				mIsFrameRenderingFinished = false;
 			}
-			else
-				mPrimaryCoreAccessor->cancelAll();
+
+			gCoreThread().queueCommand(boost::bind(&Application::updateMessagePump, this));
+			mPrimaryCoreAccessor->submitToCoreThread();
+			gCoreThread().queueCommand(boost::bind(&Application::frameRenderingFinishedCallback, this));
 
 			gTime().update();
 		}
@@ -142,6 +136,7 @@ namespace CamelotFramework
 		CM_LOCK_MUTEX(mFrameRenderingFinishedMutex);
 
 		mIsFrameRenderingFinished = true;
+		CM_THREAD_NOTIFY_ONE(mFrameRenderingFinishedCondition);
 	}
 
 	void Application::shutDown()

+ 3 - 0
TODO.txt

@@ -25,6 +25,9 @@ IMMEDIATE:
  - It's possible to resize smaller than 0 and cause an exception
  - Cursor doesn't stay inside the window we're resizing, window seems to resize slower than the cursor moves
  - OpenGL resize doesn't work - I believe its because its render thread works too slow and we call "cancelAll" on the command queue. Check out why is the render thread slow, and get rid of cancelAll(), it's not a valid approach
+  - Add special flag for commands that can or can't be dropped so I can still use "cancelAll"
+  - But just getting rid of "cancelAll" altogether is probably a better solution to get better performance, at the lost of some input lag
+    - Core and main threads should run in lockstep
  - Update debug camera so it uses callbacks
  - Add support for diacritical marks
  - onMovedOrResized is still used by Viewport