From 1fdae13de100b288b848dcdcc9a088524138b7ea Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 25 Feb 2016 17:38:20 -0800 Subject: [PATCH 1/3] Application: don't simulate until we are ready to render. --- interface/src/Application.cpp | 49 ++++++++++++----------------------- interface/src/Application.h | 1 - 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 29c8e136af..8aa27cfd86 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -210,8 +210,6 @@ static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-commands.html"; static const unsigned int THROTTLED_SIM_FRAMERATE = 15; static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; -static const unsigned int CAPPED_SIM_FRAMERATE = 120; -static const int CAPPED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / CAPPED_SIM_FRAMERATE; static const uint32_t INVALID_FRAME = UINT32_MAX; @@ -317,6 +315,9 @@ bool setupEssentials(int& argc, char** argv) { Setting::preInit(); + LogHandler::getInstance().setShouldDisplayMilliseconds(true); + LogHandler::getInstance().setShouldOutputThreadID(true); + CrashHandler::checkForAndHandleCrash(); CrashHandler::writeRunningMarkerFiler(); qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); @@ -967,6 +968,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0); + _idleTimer = new QTimer(this); connect(_idleTimer, &QTimer::timeout, [=] { idle(usecTimestampNow()); @@ -975,7 +977,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : disconnect(_idleTimer); }); // Setting the interval to zero forces this to get called whenever there are no messages - // in the queue, which can be pretty damn frequent. Hence the idle function has a bunch + // in the queue, which can be pretty damn frequent. Hence the idle function has a bunch // of logic to abort early if it's being called too often. _idleTimer->start(0); } @@ -1296,6 +1298,7 @@ void Application::initializeUi() { } void Application::paintGL() { + // paintGL uses a queued connection, so we can get messages from the queue even after we've quit // and the plugins have shutdown if (_aboutToQuit) { @@ -1321,10 +1324,6 @@ void Application::paintGL() { _lastFramesPerSecondUpdate = now; } - if (_isGLInitialized) { - idle(now); - } - PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("paintGL"); @@ -1619,7 +1618,6 @@ void Application::paintGL() { } _lastInstantaneousFps = instantaneousFps; - _pendingPaint = false; } void Application::runTests() { @@ -2432,10 +2430,11 @@ bool Application::acceptSnapshot(const QString& urlString) { static uint32_t _renderedFrameIndex { INVALID_FRAME }; void Application::idle(uint64_t now) { + if (_aboutToQuit) { return; // bail early, nothing to do here. } - + auto displayPlugin = getActiveDisplayPlugin(); // depending on whether we're throttling or not. // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in @@ -2456,30 +2455,16 @@ void Application::idle(uint64_t now) { _renderedFrameIndex = INVALID_FRAME; } - // Nested ifs are for clarity in the logic. Don't collapse them into a giant single if. // Don't saturate the main thread with rendering, no paint calls until the last one is complete - if (!_pendingPaint) { - // Also no paint calls until the display plugin has increased by at least one frame - // (don't render at 90fps if the display plugin only goes at 60) - if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) { - // Record what present frame we're on - _renderedFrameIndex = presentCount; - // Don't allow paint requests to stack up in the event queue - _pendingPaint = true; - // But when we DO request a paint, get to it as soon as possible: high priority - postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); - } - } - - // For the rest of idle, we want to cap at the max sim rate, so we might not call - // the remaining idle work every paint frame, or vice versa - // In theory this means we could call idle processing more often than painting, - // but in practice, when the paintGL calls aren't keeping up, there's no room left - // in the main thread to call idle more often than paint. - // This check is mostly to keep idle from burning up CPU cycles by running at - // hundreds of idles per second when the rendering is that fast - if ((timeSinceLastUpdateUs / USECS_PER_MSEC) < CAPPED_SIM_FRAME_PERIOD_MS) { - // No paint this round, but might be time for a new idle, otherwise return + // Also no paint calls until the display plugin has increased by at least one frame + // (don't render at 90fps if the display plugin only goes at 60) + if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) { + // Record what present frame we're on + _renderedFrameIndex = presentCount; + + // But when we DO request a paint, get to it as soon as possible: high priority + postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); + } else { return; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 51b90bcb99..cfa87ea411 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -509,7 +509,6 @@ private: int _avatarAttachmentRequest = 0; bool _settingsLoaded { false }; - bool _pendingPaint { false }; QTimer* _idleTimer { nullptr }; bool _fakedMouseEvent { false }; From 08c16beff26e4eb93b10a7d459309606fa4c389a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 25 Feb 2016 18:17:42 -0800 Subject: [PATCH 2/3] Application: re-worded presentCount comments --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e74e842f9d..caff5e7e46 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2455,16 +2455,16 @@ void Application::idle(uint64_t now) { _renderedFrameIndex = INVALID_FRAME; } - // Don't saturate the main thread with rendering, no paint calls until the last one is complete - // Also no paint calls until the display plugin has increased by at least one frame - // (don't render at 90fps if the display plugin only goes at 60) + // Don't saturate the main thread with rendering and simulation, + // unless display plugin has increased by at least one frame if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) { // Record what present frame we're on _renderedFrameIndex = presentCount; - // But when we DO request a paint, get to it as soon as possible: high priority + // request a paint, get to it as soon as possible: high priority postEvent(this, new QEvent(static_cast(Paint)), Qt::HighEventPriority); } else { + // there's no use in simulating or rendering faster then the present rate. return; } From e5c81f66a54c8c9603fa03bd5e822d8aa67de055 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 25 Feb 2016 18:20:43 -0800 Subject: [PATCH 3/3] Application: removed threadID and milliseconds from logging. --- interface/src/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index caff5e7e46..283b66b29e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -315,9 +315,6 @@ bool setupEssentials(int& argc, char** argv) { Setting::preInit(); - LogHandler::getInstance().setShouldDisplayMilliseconds(true); - LogHandler::getInstance().setShouldOutputThreadID(true); - CrashHandler::checkForAndHandleCrash(); CrashHandler::writeRunningMarkerFiler(); qAddPostRoutine(CrashHandler::deleteRunningMarkerFile);