checkpoint: it works!

This commit is contained in:
Howard Stearns 2015-11-19 09:18:40 -08:00
parent 42a1ee353e
commit 7d30cd0159
5 changed files with 25 additions and 30 deletions

View file

@ -1095,20 +1095,24 @@ void Application::paintGL() {
_inPaint = true;
Finally clearFlagLambda([this] { _inPaint = false; });
_lastInstantaneousFps = instantaneousFps;
// Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't
// include time waiting for vsync, and which can report a number above target if we've got the headroom.
// For example, if we're shooting for 75fps and paintWait is 3.3333ms (= 75% * 13.33ms), our deducedNonVSyncFps
// would be 100fps. In principle, a paintWait of zero would have deducedNonVSyncFps=75.
// Here we make a guess for deducedNonVSyncFps = 1 / deducedNonVSyncPeriod.
//
// Time between previous paintGL call and this one, which can vary not only with vSync misses, but also with QT timing.
// This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second.
// Note that _lastPaintWait (stored at end of last call) is for the same paint cycle.
const float actualPeriod = diff / (float)USECS_PER_SECOND; // same as 1/instantaneousFps but easier for compiler to optimize
// Note that _lastPaintWait (stored at end of last call) is for the same paint cycle.
float deducedNonVSyncPeriod = actualPeriod - _lastPaintWait; // plus a some non-zero time for machinery we can't measure
// We don't know how much time to allow for that, but if we went over the target period, we know it's at least the portion
// of paintWait up to the next vSync.
const float targetPeriod = isHMDMode() ? 1.0f / 75.0f : 1.0f / 60.0f;
const float nSyncsByFrameRate = round(actualPeriod / targetPeriod);
const float accuracyAllowance = 0.0005f; // sometimes paint goes over and it isn't reflected in actualPeriod
const float nSyncsByPaintWait = floor((_lastPaintWait + accuracyAllowance) / targetPeriod);
const float nSyncs = nSyncsByFrameRate + nSyncsByPaintWait;
const float modularPeriod = ((nSyncs - 1) * targetPeriod) + actualPeriod;
const float deducedNonVSyncPeriod = modularPeriod - _lastPaintWait;
const float minumumMachinery = glm::max(0.0f, (floorf(_lastPaintWait / targetPeriod) * targetPeriod) - _lastPaintWait);
deducedNonVSyncPeriod += minumumMachinery;
_lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod;
_lastInstantaneousFps = instantaneousFps;
auto displayPlugin = getActiveDisplayPlugin();
displayPlugin->preRender();

View file

@ -192,7 +192,7 @@ void Avatar::simulate(float deltaTime) {
_shouldRenderBillboard = true;
qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
}
#define PID_TUNING 1
//#define PID_TUNING 1
#ifdef PID_TUNING
const float SKIP_HYSTERESIS_PROPORTION = 0.0f;
#else

View file

@ -102,16 +102,10 @@ void AvatarManager::init() {
// See PIDController.h. There's a sectionon tuning in the reference.
// Turn off HYSTERESIS_PROPORTION and extra logging by defining PID_TUNING in Avatar.cpp.
// Turn on logging with the following:
_renderDistanceController.setHistorySize("avatar render", target_fps * 4); // FIXME
// KP is usually tuned by setting the other constants to zero, finding the maximum value that doesn't oscillate,
// and taking about 0.6 of that. A typical osciallation would be with error=37fps with avatars 10m away, so
// KP*37=1/10 => KP(oscillating)=0.1/37 = 0.0027
_renderDistanceController.setKP(0.0015f);
// alt:
// Our anti-windup limits accumulated error to 10*targetFrameRate, so the sanity check on KI is
// KI*750=controlledValueHighLimit=1 => KI=1/750.
_renderDistanceController.setKI(0.001f);
_renderDistanceController.setKD(0.0001f); // a touch of kd increases the speed by which we get there
//_renderDistanceController.setHistorySize("avatar render", target_fps * 4); // FIXME
_renderDistanceController.setKP(0.0003f); //Usually about 0.6 of largest that doesn't oscillate, with other constants 0.
_renderDistanceController.setKI(0.001f); // Big enough to bring us to target with the above KP.
_renderDistanceController.setKD(0.00001f); // a touch of kd increases the speed by which we get there
}
@ -140,18 +134,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
PerformanceTimer perfTimer("otherAvatars");
const float FEED_FORWARD_RANGE = 2;
const float fps = qApp->getLastInstanteousFps();
const float paintWait = qApp->getLastPaintWait();
const float deduced = qApp->getLastDeducedNonVSyncFps();
const bool isAtSetpoint = false; //FIXME fabsf(effectiveFps - _renderDistanceController.getMeasuredValueSetpoint()) < FEED_FORWARD_RANGE;
//const float distance = 1.0f / _renderDistanceController.update(deduced + (isAtSetpoint ? _renderFeedForward : 0.0f), deltaTime, isAtSetpoint, fps, paintWait);
const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, isAtSetpoint, fps, paintWait);
const float RENDER_DISTANCE_DEADBAND = 0.0f; //FIXME 0.3f; // meters
if (fabsf(distance - _renderDistance) > RENDER_DISTANCE_DEADBAND) {
_renderDistance = distance;
}
const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime, false, fps, paintWait);
_renderDistanceAverage.updateAverage(distance);
_renderDistance = _renderDistanceAverage.getAverage();
// simulate avatars
AvatarHash::iterator avatarIterator = _avatarHash.begin();

View file

@ -19,6 +19,7 @@
#include <AvatarHashMap.h>
#include <PhysicsEngine.h>
#include <PIDController.h>
#include <SimpleMovingAverage.h>
#include "Avatar.h"
#include "AvatarMotionState.h"
@ -106,6 +107,8 @@ private:
float _renderFeedForward { 5.0f };
int _renderedAvatarCount {0};
PIDController _renderDistanceController {};
SimpleMovingAverage _renderDistanceAverage {10};
SetOfAvatarMotionStates _avatarMotionStates;

View file

@ -71,7 +71,7 @@ void PIDController::reportHistory() {
Row& row = _history[i];
qCDebug(shared) << row.measured << (row.dt * 1000) << row.FIXME1 << (row.FIXME2 * 1000) <<
"||" << row.error << row.accumulated << row.changed <<
"||" << row.p << row.i << row.d << row.computed;
"||" << row.p << row.i << row.d << row.computed << 1.0f/row.computed;
}
qCDebug(shared) << "Limits: setpoint" << getMeasuredValueSetpoint() << "accumulate" << getAccumulatedValueLowLimit() << getAccumulatedValueHighLimit() <<
"controlled" << getControlledValueLowLimit() << getControlledValueHighLimit() <<