[OpenTK] Fix UpdateFrame quantization error

The UpdateFrame event rate will now match TargetUpdatePeriod even if
vsync is enabled. Previously, it would be quantized to a multiple or
integer fraction of of the vsync rate.
This commit is contained in:
Stefanos A. 2014-01-14 13:04:30 +01:00
parent 3eccb89821
commit 97e49b76b2

View file

@ -90,6 +90,8 @@ namespace OpenTK
double update_timestamp; // timestamp of last UpdateFrame event double update_timestamp; // timestamp of last UpdateFrame event
double render_timestamp; // timestamp of last RenderFrame event double render_timestamp; // timestamp of last RenderFrame event
double update_epsilon; // quantization error for UpdateFrame events
VSyncMode vsync; VSyncMode vsync;
FrameEventArgs update_args = new FrameEventArgs(); FrameEventArgs update_args = new FrameEventArgs();
@ -439,26 +441,22 @@ namespace OpenTK
void DispatchUpdateAndRenderFrame(object sender, EventArgs e) void DispatchUpdateAndRenderFrame(object sender, EventArgs e)
{ {
double timestamp = watch.Elapsed.TotalSeconds; double timestamp = watch.Elapsed.TotalSeconds;
double elapsed = ClampElapsed(timestamp - update_timestamp); double elapsed = 0;
// Calculate how many update events we need to execute in order to reach elapsed = ClampElapsed(timestamp - update_timestamp);
// our desired TargetUpdateFrequency while (elapsed > 0 && elapsed + update_epsilon >= TargetUpdatePeriod)
int update_count = TargetUpdatePeriod != 0 ?
(int)(elapsed / TargetUpdatePeriod) :
1;
while (update_count > 0)
{ {
// Raise UpdateFrame events until we catch up with our target update rate. RaiseUpdateFrame(elapsed, ref timestamp);
if (elapsed > 0)
{ // Calculate difference (positive or negative) between
RaiseUpdateFrame(elapsed, ref timestamp); // actual elapsed time and target elapsed time. We must
--update_count; // compensate for this difference.
} update_epsilon += elapsed - TargetUpdatePeriod;
// Prepare for next loop
elapsed = ClampElapsed(timestamp - update_timestamp); elapsed = ClampElapsed(timestamp - update_timestamp);
} }
//timestamp = watch.Elapsed.TotalSeconds;
elapsed = ClampElapsed(timestamp - render_timestamp); elapsed = ClampElapsed(timestamp - render_timestamp);
if (elapsed > 0 && elapsed >= TargetRenderPeriod) if (elapsed > 0 && elapsed >= TargetRenderPeriod)
{ {