diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a03cad62a..32500a9996 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1124,29 +1124,6 @@ void Application::paintGL() { _inPaint = true; Finally clearFlagLambda([this] { _inPaint = false; }); - // 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. - // We're using this as a proxy for the time between vsync and displayEnd, below. (Not exact, but tends to be the same over time.) - // This is not the same as update(deltaTime), because the latter attempts to throttle to 60hz and also clamps to 1/4 second. - 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 + _marginForDeducedFramePeriod; // 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. This gives us enough of a penalty so that when actualPeriod crosses two cycles, - // the key part (and not an exagerated part) of _lastPaintWait is accounted for. - const float targetPeriod = getTargetFramePeriod(); - if (_lastPaintWait > EPSILON && actualPeriod > targetPeriod) { - // Don't use C++ remainder(). It's authors are mathematically insane. - deducedNonVSyncPeriod += fmod(actualPeriod, _lastPaintWait); - } - _lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod; - _lastInstantaneousFps = instantaneousFps; - auto displayPlugin = getActiveDisplayPlugin(); // FIXME not needed anymore? _offscreenContext->makeCurrent(); @@ -1403,7 +1380,6 @@ void Application::paintGL() { Q_ASSERT(!_lockedFramebufferMap.contains(finalTexture)); _lockedFramebufferMap[finalTexture] = scratchFramebuffer; - uint64_t displayStart = usecTimestampNow(); Q_ASSERT(isCurrentContext(_offscreenContext->getContext())); { PROFILE_RANGE(__FUNCTION__ "/pluginSubmitScene"); @@ -1412,9 +1388,6 @@ void Application::paintGL() { } Q_ASSERT(isCurrentContext(_offscreenContext->getContext())); - uint64_t displayEnd = usecTimestampNow(); - const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs - _lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND; } { @@ -1425,6 +1398,14 @@ void Application::paintGL() { batch.resetStages(); }); } + + // Some LOD-like controls need to know a smoothly varying "potential" frame rate that doesn't + // include time waiting for sync, and which can report a number above target if we've got the headroom. + // In my tests, the following is mostly less than 0.5ms, and never more than 3ms. I don't think its worth measuring during runtime. + const float paintWaitAndQTTimerAllowance = 0.001f; // seconds + // Store both values now for use by next cycle. + _lastInstantaneousFps = instantaneousFps; + _lastUnsynchronizedFps = 1.0f / (((usecTimestampNow() - now) / (float)USECS_PER_SECOND) + paintWaitAndQTTimerAllowance); } void Application::runTests() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 27df7835e6..b7cdf3ff74 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -163,11 +163,8 @@ public: float const HMD_TARGET_FRAME_RATE = 75.0f; float const DESKTOP_TARGET_FRAME_RATE = 60.0f; float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; } - float getTargetFramePeriod() { return isHMDMode() ? 1.0f / HMD_TARGET_FRAME_RATE : 1.0f / DESKTOP_TARGET_FRAME_RATE; } // same as 1/getTargetFrameRate, but w/compile-time division float getLastInstanteousFps() const { return _lastInstantaneousFps; } - float getLastPaintWait() const { return _lastPaintWait; }; - float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; } - void setMarginForDeducedFramePeriod(float newValue) { _marginForDeducedFramePeriod = newValue; } + float getLastUnsynchronizedFps() const { return _lastUnsynchronizedFps; } float getFieldOfView() { return _fieldOfView.get(); } void setFieldOfView(float fov); @@ -443,9 +440,7 @@ private: QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; float _lastInstantaneousFps { 0.0f }; - float _lastPaintWait { 0.0f }; - float _lastDeducedNonVSyncFps { 0.0f }; - float _marginForDeducedFramePeriod{ 0.002f }; // 2ms, adjustable + float _lastUnsynchronizedFps { 0.0f }; ShapeManager _shapeManager; PhysicalEntitySimulation _entitySimulation; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 4e3d9b92fe..59af6b18df 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -111,7 +111,6 @@ void AvatarManager::init() { _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. - } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -151,7 +150,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // The measured value is frame rate. When the controlled value (1 / render cutoff distance) // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate // goes up. - const float deduced = qApp->getLastDeducedNonVSyncFps(); + const float deduced = qApp->getLastUnsynchronizedFps(); const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); _renderDistanceAverage.updateAverage(distance); _renderDistance = _renderDistanceAverage.getAverage(); diff --git a/libraries/shared/src/PIDController.cpp b/libraries/shared/src/PIDController.cpp index a853553b89..78aa31e4c7 100644 --- a/libraries/shared/src/PIDController.cpp +++ b/libraries/shared/src/PIDController.cpp @@ -65,7 +65,7 @@ void PIDController::updateHistory(float measuredValue, float dt, float error, fl } } void PIDController::reportHistory() { - qCDebug(shared) << _label << "measured dt FIXME || error accumulated changed || p i d controlled"; + qCDebug(shared) << _label << "measured dt || error accumulated changed || p i d controlled"; for (int i = 0; i < _history.size(); i++) { Row& row = _history[i]; qCDebug(shared) << row.measured << row.dt <<