From f9718913e27c8eae0314bb340110d69c5441bae7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 27 Feb 2014 16:13:05 -0800 Subject: [PATCH 1/2] fix octree-server random spinout sometimes when client disconnects --- .../src/octree/OctreeQueryNode.cpp | 22 ++++++++++--------- .../src/octree/OctreeSendThread.cpp | 14 +++++++++++- .../src/octree/OctreeSendThread.h | 3 +++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 633ee3ede1..3ff9d6820b 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -37,6 +37,18 @@ OctreeQueryNode::OctreeQueryNode() : _sequenceNumber = 0; } +OctreeQueryNode::~OctreeQueryNode() { + if (_octreeSendThread) { + _octreeSendThread->terminate(); + delete _octreeSendThread; + } + + delete[] _octreePacket; + delete[] _lastOctreePacket; +} + + + void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID) { // Create octree sending thread... _octreeSendThread = new OctreeSendThread(nodeUUID, octreeServer); @@ -158,16 +170,6 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, int bytes) { } } -OctreeQueryNode::~OctreeQueryNode() { - if (_octreeSendThread) { - _octreeSendThread->terminate(); - delete _octreeSendThread; - } - - delete[] _octreePacket; - delete[] _lastOctreePacket; -} - bool OctreeQueryNode::updateCurrentViewFrustum() { bool currentViewFrustumChanged = false; ViewFrustum newestViewFrustum; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 8e7d9c37c6..cbfa8f0415 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -20,7 +20,8 @@ quint64 endSceneSleepTime = 0; OctreeSendThread::OctreeSendThread(const QUuid& nodeUUID, OctreeServer* myServer) : _nodeUUID(nodeUUID), _myServer(myServer), - _packetData() + _packetData(), + _nodeMissingCount(0) { qDebug() << "client connected"; _myServer->clientConnected(); @@ -33,6 +34,14 @@ OctreeSendThread::~OctreeSendThread() { bool OctreeSendThread::process() { + + const int MAX_NODE_MISSING_CHECKS = 10; + if (_nodeMissingCount > MAX_NODE_MISSING_CHECKS) { + qDebug() << "our target node:" << _nodeUUID << "has been missing the last" << _nodeMissingCount + << "times we checked, we are going to stop attempting to send."; + return false; // stop processing and shutdown, our node no longer exists + } + quint64 start = usecTimestampNow(); bool gotLock = false; @@ -41,6 +50,7 @@ bool OctreeSendThread::process() { SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID); if (node) { + _nodeMissingCount = 0; // make sure the node list doesn't kill our node while we're using it if (node->getMutex().tryLock()) { gotLock = true; @@ -61,6 +71,8 @@ bool OctreeSendThread::process() { node->getMutex().unlock(); // we're done with this node for now. } + } else { + _nodeMissingCount++; } } else { if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 3554dcdfef..081e7f411f 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -16,6 +16,7 @@ #include "OctreeQueryNode.h" #include "OctreeServer.h" + /// Threaded processor for sending voxel packets to a single client class OctreeSendThread : public GenericThread { public: @@ -41,6 +42,8 @@ private: int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged); OctreePacketData _packetData; + + int _nodeMissingCount; }; #endif // __octree_server__OctreeSendThread__ From 19b71892692a6754571ea7ee5653a9c14008267a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 27 Feb 2014 18:00:58 -0800 Subject: [PATCH 2/2] switch AUTO LOD to use moving avarage of FPS, and also tweak the min and max behavior --- interface/src/Menu.cpp | 33 ++++++++++++++++++++++++++++----- interface/src/Menu.h | 3 ++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 830ac17ebd..a33b4ee5d5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -56,6 +56,7 @@ Menu* Menu::getInstance() { const ViewFrustumOffset DEFAULT_FRUSTUM_OFFSET = {-135.0f, 0.0f, 0.0f, 25.0f, 0.0f}; const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; +const int FIVE_SECONDS_OF_FRAMES = 5 * 60; Menu::Menu() : _actionHash(), @@ -72,6 +73,7 @@ Menu::Menu() : _boundaryLevelAdjust(0), _maxVoxelPacketsPerSecond(DEFAULT_MAX_VOXEL_PPS), _lastAdjust(usecTimestampNow()), + _fpsAverage(FIVE_SECONDS_OF_FRAMES), _loginAction(NULL) { Application *appInstance = Application::getInstance(); @@ -1105,22 +1107,43 @@ void Menu::voxelStatsDetailsClosed() { } void Menu::autoAdjustLOD(float currentFPS) { + // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't + // really want to count them in our average, so we will ignore the real frame rates and stuff + // our moving average with simulated good data + const int IGNORE_THESE_SAMPLES = 100; + const float ASSUMED_FPS = 60.0f; + if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) { + currentFPS = ASSUMED_FPS; + } + _fpsAverage.updateAverage(currentFPS); + bool changed = false; quint64 now = usecTimestampNow(); quint64 elapsed = now - _lastAdjust; - - if (elapsed > ADJUST_LOD_DOWN_DELAY && currentFPS < ADJUST_LOD_DOWN_FPS && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { + + if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS + && _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { + _voxelSizeScale *= ADJUST_LOD_DOWN_BY; + if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { + _voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; + } changed = true; _lastAdjust = now; - qDebug() << "adjusting LOD down... currentFPS=" << currentFPS << "_voxelSizeScale=" << _voxelSizeScale; + qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() + << "_voxelSizeScale=" << _voxelSizeScale; } - if (elapsed > ADJUST_LOD_UP_DELAY && currentFPS > ADJUST_LOD_UP_FPS && _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { + if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS + && _voxelSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { _voxelSizeScale *= ADJUST_LOD_UP_BY; + if (_voxelSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { + _voxelSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; + } changed = true; _lastAdjust = now; - qDebug() << "adjusting LOD up... currentFPS=" << currentFPS << "_voxelSizeScale=" << _voxelSizeScale; + qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() + << "_voxelSizeScale=" << _voxelSizeScale; } if (changed) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 84a5eef481..3d8aa24cbd 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -27,7 +27,7 @@ const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2; const float ADJUST_LOD_DOWN_BY = 0.9f; const float ADJUST_LOD_UP_BY = 1.1f; -const float ADJUST_LOD_MIN_SIZE_SCALE = TREE_SCALE * 1.0f; +const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f; const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; enum FrustumDrawMode { @@ -193,6 +193,7 @@ private: QMenu* _activeScriptsMenu; QString replaceLastOccurrence(QChar search, QChar replace, QString string); quint64 _lastAdjust; + SimpleMovingAverage _fpsAverage; QAction* _loginAction; };