Time out here!
There are two reasons two throttle frame rate.
1. Conserve CPU time and leave more cpu time for other tasks. Using sleep() calls you can put FG asleep for a short time if it gets done drawing a frame early, leaving those cycles for other tasks.
2. Accurately control frame rate. Here you want to run at a fixed precise frame rate to achieve smooth, jitter free rendering. For instance, if you can't quite sustain 60hz consistanty, you might want to throttle back to 30hz.
The problem is that this new patch throws away the second reason in favor of the first. When I throttle to 20hz, I get 19hz. When I throttle to 30hz I get, ohh ... 28 or 29 depending. Putting the application to sleep does terrible things to timing accuracy, because typically the application can only wake up during a kernel trap, and if you miss the vertical refresh by even 1 millesecond, you drop a frame and get animation jitters.
Maybe we need to figure out how to satisfy both needs, but we can't just blindly dispense with reason #2 when a new need comes along.
Maybe we need separate options, such as --cpu-friendly-inaccurate-throttle-with-sleep-hz= and --frame-rate-accurate-throttle=
Thoughts? I think we need to tread a bit more carefully on this one, especially since I have a side project that employs this option (well, used to employ this option) :-( to achieve accurate frame rate timing and smooth animation.
Curt.
Erik Hofman wrote:
Update of /var/cvs/FlightGear-0.9/FlightGear/src/Main In directory baron:/tmp/cvs-serv28989
Modified Files:
main.cxx Log Message:
Frederic Bouvier:
Norman Vine wrote :
Frederic Bouvier writes:
Quoting Andy Ross:
* Hopefully in a CPU-friendly way. I know that older versions ofeven with sync to vblank enabled. The CPU usage is always 100%.
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
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.
Index: main.cxx
===================================================================
RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Main/main.cxx,v
retrieving revision 1.193
retrieving revision 1.194
diff -C2 -r1.193 -r1.194
*** main.cxx 5 Jan 2005 05:45:38 -0000 1.193
--- main.cxx 9 Mar 2005 15:12:01 -0000 1.194
***************
*** 223,226 ****
--- 223,228 ----
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;
***************
*** 231,241 ****
double throttle_hz = fgGetDouble("/sim/frame-rate-throttle-hz", 0.0);
! if ( throttle_hz > 0.0 ) {
// simple frame rate throttle
! double dt = 1000000.0 / throttle_hz;
current_time_stamp.stamp();
! while ( current_time_stamp - last_time_stamp < dt ) {
! current_time_stamp.stamp();
}
} else {
// run as fast as the app will go
--- 233,250 ----
double throttle_hz = fgGetDouble("/sim/frame-rate-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 + remainder;
! int wait = dt / 1000;
! remainder = dt - ( wait * 1000.0 );
! 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
***************
*** 422,427 ****
}
- bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
- // flight model
if ( global_multi_loop > 0) {
--- 431,434 ----
_______________________________________________
Flightgear-cvslogs mailing list
[EMAIL PROTECTED]
http://mail.flightgear.org/mailman/listinfo/flightgear-cvslogs
2f585eeea02e2c79d7b1d8c4963bae2d
-- Curtis Olson http://www.flightgear.org/~curt HumanFIRST Program http://www.humanfirst.umn.edu/ FlightGear Project http://www.flightgear.org Unique text: 2f585eeea02e2c79d7b1d8c4963bae2d
_______________________________________________ Flightgear-devel mailing list [email protected] http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
