mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-30 09:30:35 +02:00
Merge pull request #6601 from howard-stearns/fix-sync-period-calc
Fix sync period calc, restoring avatar render distance
This commit is contained in:
commit
a99542e298
4 changed files with 12 additions and 37 deletions
|
@ -1124,29 +1124,6 @@ void Application::paintGL() {
|
||||||
_inPaint = true;
|
_inPaint = true;
|
||||||
Finally clearFlagLambda([this] { _inPaint = false; });
|
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();
|
auto displayPlugin = getActiveDisplayPlugin();
|
||||||
// FIXME not needed anymore?
|
// FIXME not needed anymore?
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
@ -1403,7 +1380,6 @@ void Application::paintGL() {
|
||||||
Q_ASSERT(!_lockedFramebufferMap.contains(finalTexture));
|
Q_ASSERT(!_lockedFramebufferMap.contains(finalTexture));
|
||||||
_lockedFramebufferMap[finalTexture] = scratchFramebuffer;
|
_lockedFramebufferMap[finalTexture] = scratchFramebuffer;
|
||||||
|
|
||||||
uint64_t displayStart = usecTimestampNow();
|
|
||||||
Q_ASSERT(isCurrentContext(_offscreenContext->getContext()));
|
Q_ASSERT(isCurrentContext(_offscreenContext->getContext()));
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(__FUNCTION__ "/pluginSubmitScene");
|
PROFILE_RANGE(__FUNCTION__ "/pluginSubmitScene");
|
||||||
|
@ -1412,9 +1388,6 @@ void Application::paintGL() {
|
||||||
}
|
}
|
||||||
Q_ASSERT(isCurrentContext(_offscreenContext->getContext()));
|
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();
|
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() {
|
void Application::runTests() {
|
||||||
|
|
|
@ -163,11 +163,8 @@ public:
|
||||||
float const HMD_TARGET_FRAME_RATE = 75.0f;
|
float const HMD_TARGET_FRAME_RATE = 75.0f;
|
||||||
float const DESKTOP_TARGET_FRAME_RATE = 60.0f;
|
float const DESKTOP_TARGET_FRAME_RATE = 60.0f;
|
||||||
float getTargetFrameRate() { return isHMDMode() ? HMD_TARGET_FRAME_RATE : DESKTOP_TARGET_FRAME_RATE; }
|
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 getLastInstanteousFps() const { return _lastInstantaneousFps; }
|
||||||
float getLastPaintWait() const { return _lastPaintWait; };
|
float getLastUnsynchronizedFps() const { return _lastUnsynchronizedFps; }
|
||||||
float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; }
|
|
||||||
void setMarginForDeducedFramePeriod(float newValue) { _marginForDeducedFramePeriod = newValue; }
|
|
||||||
|
|
||||||
float getFieldOfView() { return _fieldOfView.get(); }
|
float getFieldOfView() { return _fieldOfView.get(); }
|
||||||
void setFieldOfView(float fov);
|
void setFieldOfView(float fov);
|
||||||
|
@ -443,9 +440,7 @@ private:
|
||||||
QElapsedTimer _timerStart;
|
QElapsedTimer _timerStart;
|
||||||
QElapsedTimer _lastTimeUpdated;
|
QElapsedTimer _lastTimeUpdated;
|
||||||
float _lastInstantaneousFps { 0.0f };
|
float _lastInstantaneousFps { 0.0f };
|
||||||
float _lastPaintWait { 0.0f };
|
float _lastUnsynchronizedFps { 0.0f };
|
||||||
float _lastDeducedNonVSyncFps { 0.0f };
|
|
||||||
float _marginForDeducedFramePeriod{ 0.002f }; // 2ms, adjustable
|
|
||||||
|
|
||||||
ShapeManager _shapeManager;
|
ShapeManager _shapeManager;
|
||||||
PhysicalEntitySimulation _entitySimulation;
|
PhysicalEntitySimulation _entitySimulation;
|
||||||
|
|
|
@ -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.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.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.
|
_renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::updateMyAvatar(float deltaTime) {
|
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)
|
// 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, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate
|
||||||
// goes up.
|
// goes up.
|
||||||
const float deduced = qApp->getLastDeducedNonVSyncFps();
|
const float deduced = qApp->getLastUnsynchronizedFps();
|
||||||
const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime);
|
const float distance = 1.0f / _renderDistanceController.update(deduced, deltaTime);
|
||||||
_renderDistanceAverage.updateAverage(distance);
|
_renderDistanceAverage.updateAverage(distance);
|
||||||
_renderDistance = _renderDistanceAverage.getAverage();
|
_renderDistance = _renderDistanceAverage.getAverage();
|
||||||
|
|
|
@ -65,7 +65,7 @@ void PIDController::updateHistory(float measuredValue, float dt, float error, fl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void PIDController::reportHistory() {
|
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++) {
|
for (int i = 0; i < _history.size(); i++) {
|
||||||
Row& row = _history[i];
|
Row& row = _history[i];
|
||||||
qCDebug(shared) << row.measured << row.dt <<
|
qCDebug(shared) << row.measured << row.dt <<
|
||||||
|
|
Loading…
Reference in a new issue