]> git.mxchange.org Git - flightgear.git/commitdiff
Frederic Bouvier:
authorehofman <ehofman>
Wed, 9 Mar 2005 15:12:01 +0000 (15:12 +0000)
committerehofman <ehofman>
Wed, 9 Mar 2005 15:12:01 +0000 (15:12 +0000)
Norman Vine wrote :

> Frederic Bouvier writes:
>
>> Quoting Andy Ross:
>>> * Hopefully in a CPU-friendly way.  I know that older versions of
>>>  the NVidia drivers did this by spinning in a polling loop
>>>  inside the driver.  I'm not sure if this has been fixed or not.
>>>
>>> From my experience, the latest non-beta Windows NVidia driver seems to eat CPU
>>
>> even with sync to vblank enabled. The CPU usage is always 100%.
>
> Buried in the PPE sources is a 'hackish' but portable way to limit CPU usage if the desired framerate is met
>
>  /*
>    Frame Rate Limiter.
>
>    This prevents any one 3D window from updating faster than
>    about 60Hz.  This saves a ton of CPU time on fast machines.
>
>    ! I THINK I MUNGED THE VALUE FOR ulMilliSecondSleep() NHV !
>  */
>
>  static ulClock *ck = NULL ;
>
>  if ( frame_rate_limiter )
>  {
>     if ( ck == NULL )
>     {
>       ck = new ulClock ;
>       ck -> update () ;
>     }
>
>     int t_ms = (int) ( ck->getDeltaTime() * 1000.0 ) ; /* Convert to ms */
>
>     if ( t_ms < 16 )
>       ulMilliSecondSleep ( 16 - t_ms ) ;
>  }
>
>

I implemented the method pointed out by Norman. It works great on windows and saves me a lot of CPU cycles. This way, I can get the same framerate in moderately populated areas and have CPU idle 50% of the time instead of wildly looping in the NVidia driver while waiting to sync on vblank.

It has been tested on Linux by Melchior. He saw the same gain in CPU cycles.

src/Main/main.cxx

index 83d3add39904a22f5f6f4a54b2d44bf119b7599d..db569b84ee1d8ac2234e0fa73797a4c6fe407ce7 100644 (file)
@@ -222,6 +222,8 @@ static void fgMainLoop( void ) {
 
     SGCloudLayer::enable_bump_mapping = fgGetBool("/sim/rendering/bump-mapping");
 
+    bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
+
     // Update the elapsed time.
     static bool first_time = true;
     if ( first_time ) {
@@ -230,13 +232,20 @@ static void fgMainLoop( void ) {
     }
 
     double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
-    if ( throttle_hz > 0.0 ) {
+    if ( throttle_hz > 0.0 && scenery_loaded ) {
+        static double remainder = 0.0;
+
         // simple frame rate throttle
-        double dt = 1000000.0 / throttle_hz;
+        double dt = 1000000.0 / throttle_hz + remainder;
+        int wait = dt / 1000;
+        remainder = dt - ( wait * 1000.0 );
+
         current_time_stamp.stamp();
-        while ( current_time_stamp - last_time_stamp < dt ) {
-            current_time_stamp.stamp();
+        int t_ms = (int) ( ( current_time_stamp - last_time_stamp ) / 1000 ) ; /* Convert to ms */
+        if ( t_ms < wait ) {
+            ulMilliSecondSleep ( wait - t_ms ) ;
         }
+        current_time_stamp.stamp();
     } else {
         // run as fast as the app will go
         current_time_stamp.stamp();
@@ -421,8 +430,6 @@ static void fgMainLoop( void ) {
         remainder = 0;
     }
 
-    bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
-
     // flight model
     if ( global_multi_loop > 0) {
         // first run the flight model each frame until it is intialized